import type { Project } from '@lib/schema';

/* InboxIntel case study. Source: F:\Documents\InboxIntel\InboxIntel (README + docs). */
export const inboxintel: Project = {
  id: 'inboxintel',
  name: 'InboxIntel',
  order: 2,
  status: 'in-development',
  template: 'case-study',
  stack: [
    { name: '.NET 8', context: { en: 'ASP.NET Core', no: 'ASP.NET Core' } },
    { name: 'PostgreSQL', context: { en: 'EF Core + Npgsql', no: 'EF Core + Npgsql' } },
    { name: 'React 18', context: { en: 'Vite · Chart.js', no: 'Vite · Chart.js' } },
    { name: 'Gmail API', context: { en: 'OAuth2 · Polly', no: 'OAuth2 · Polly' } },
    { name: 'Serilog' },
    { name: 'Docker' },
  ],
  links: [],
  diagram: {
    viewBox: '0 0 1120 300',
    title: { en: 'InboxIntel architecture', no: 'InboxIntel-arkitektur' },
    desc: {
      en: 'A React SPA calls an ASP.NET Core API layered as Clean Architecture (Api → Infrastructure → Application → Domain). A hosted background worker syncs the external Gmail API into PostgreSQL with Polly retry/backoff.',
      no: 'En React-app kaller et ASP.NET Core-API bygget som Clean Architecture (Api → Infrastructure → Application → Domain). En bakgrunnstjeneste synkroniserer det eksterne Gmail-API-et inn i PostgreSQL med Polly retry/backoff.',
    },
    nodes: [
      {
        id: 'spa',
        x: 40,
        y: 116,
        w: 170,
        h: 72,
        kind: 'internal',
        label: 'React SPA',
        sub: { en: 'Vite · Chart.js', no: 'Vite · Chart.js' },
      },
      {
        id: 'api',
        x: 290,
        y: 116,
        w: 200,
        h: 72,
        kind: 'primary',
        label: 'ASP.NET Core API',
        sub: { en: 'Clean Architecture', no: 'Clean Architecture' },
      },
      {
        id: 'pg',
        x: 580,
        y: 48,
        w: 180,
        h: 64,
        kind: 'internal',
        label: 'PostgreSQL',
        sub: { en: 'EF Core · Npgsql', no: 'EF Core · Npgsql' },
      },
      {
        id: 'worker',
        x: 580,
        y: 160,
        w: 180,
        h: 64,
        kind: 'internal',
        label: 'Sync worker',
        sub: { en: 'hosted · Polly', no: 'hostet · Polly' },
      },
      {
        id: 'gmail',
        x: 900,
        y: 152,
        w: 180,
        h: 72,
        kind: 'external',
        label: 'Gmail API',
        sub: { en: 'external · OAuth2', no: 'eksternt · OAuth2' },
      },
    ],
    edges: [
      { d: 'M210 152 H290', kind: 'flow', label: '/api', labelX: 240, labelY: 144 },
      { d: 'M490 134 L580 92', kind: 'flow' },
      { d: 'M490 170 L580 192', kind: 'flow' },
      { d: 'M670 160 V112', kind: 'flow' },
      { d: 'M760 192 H900', kind: 'external', label: 'sync', labelX: 820, labelY: 184 },
    ],
  },
  media: [
    {
      src: 'placeholder:inboxintel-dashboard',
      width: 1600,
      height: 1000,
      alt: {
        en: 'InboxIntel draggable analytics dashboard with charts',
        no: 'InboxIntel dashbord med flyttbare analyse-widgets',
      },
      caption: {
        en: 'Draggable analytics dashboard (react-grid-layout)',
        no: 'Dashbord med flyttbare widgets (react-grid-layout)',
      },
    },
    {
      src: 'placeholder:inboxintel-cleanup',
      width: 1600,
      height: 1000,
      alt: {
        en: 'Bulk cleanup preview screen requiring explicit confirmation',
        no: 'Forhåndsvisning av masseopprydding som krever bekreftelse',
      },
      caption: {
        en: 'Cleanup preview — nothing is deleted without a confirmed flag',
        no: 'Oppryddings-forhåndsvisning — ingenting slettes uten bekreftelse',
      },
    },
  ],
  content: {
    en: {
      valueProp: 'Gmail analytics and safe bulk cleanup, built as a disciplined Clean Architecture.',
      cardTeaser:
        'Gmail analytics and safe bulk cleanup — Clean Architecture, encrypted OAuth tokens, preview-before-delete by design.',
      tldr: {
        what: 'Gmail analytics, cleanup and unsubscribe management with a background sync worker.',
        why: 'To practise Clean Architecture properly and make destructive operations safe by design.',
        stack: '.NET 8 · PostgreSQL · React 18 · Gmail API · Serilog · Polly · Docker.',
        role: 'Sole architect and developer, front to back.',
      },
      sections: [
        {
          kind: 'problem',
          heading: 'Problem & context',
          anchorId: 'problem',
          blocks: [
            {
              type: 'p',
              text: 'A busy inbox needs analytics and cleanup, but bulk operations on real mail are dangerous — one wrong filter can delete things you can’t get back. I built InboxIntel to explore two things at once: a clean, testable backend architecture, and destructive operations that are safe by construction.',
            },
          ],
        },
        {
          kind: 'architecture',
          heading: 'Architecture',
          anchorId: 'architecture',
          blocks: [
            {
              type: 'p',
              text: 'A four-project Clean Architecture solution behind a React SPA. The dependency rule points inward: Api → Infrastructure → Application → Domain. Controllers hold no business logic — they delegate to Application-layer service interfaces resolved through DI. A hosted background worker syncs Gmail into PostgreSQL with Polly retry and backoff.',
            },
            {
              type: 'ul',
              items: [
                'Domain: entities and enums, no external dependencies.',
                'Application: service interfaces, DTOs, validators, the Gmail query parser.',
                'Infrastructure: EF Core, the Gmail client, the sync worker, AI and export.',
                'Api: ASP.NET Core controllers, auth, DI and Serilog — thin by design.',
              ],
            },
          ],
        },
        {
          kind: 'decisions',
          heading: 'Key decisions & trade-offs',
          anchorId: 'decisions',
          decisions: [
            {
              n: 1,
              choice: 'Full Clean Architecture across four projects.',
              alternative: 'A single project would have shipped faster.',
              rationale:
                'I wanted the dependency rule to be enforced by the project structure, not by discipline alone. It costs more ceremony up front and pays back in testability and clear boundaries.',
            },
            {
              n: 2,
              choice: 'Encrypt OAuth refresh tokens at rest and never log them.',
              alternative: 'Store them as plain columns.',
              rationale:
                'Refresh tokens are long-lived keys to someone’s mailbox. They’re encrypted with the ASP.NET Core Data Protection API (AES), with keys persisted to a mounted volume — the single most important security decision in the app.',
            },
            {
              n: 3,
              choice: 'Every destructive action is preview-then-confirm.',
              alternative: 'Delete immediately on request.',
              rationale:
                'All cleanup and unsubscribe actions require a server-side preview and an explicit Confirmed flag. The AI layer is advisory only and can never trigger a deletion.',
            },
          ],
        },
        {
          kind: 'security',
          heading: 'Security & production notes',
          anchorId: 'security',
          blocks: [
            {
              type: 'ul',
              items: [
                'Gmail scopes are read/modify only — no send scope is ever requested.',
                'Polly provides retry and backoff against Gmail API rate limits and transient failures.',
                'FluentValidation on inputs; Serilog structured logging that never records tokens.',
                'Unit tests cover the query parser and unsubscribe extraction; integration tests boot the API host and assert authorization is enforced.',
              ],
            },
          ],
        },
        {
          kind: 'screenshots',
          heading: 'Screenshots',
          anchorId: 'screenshots',
        },
        {
          kind: 'next',
          heading: 'Status & what’s next',
          anchorId: 'next',
          blocks: [
            {
              type: 'p',
              text: 'InboxIntel is in active development: the architecture is complete and the layers compile and are wired end to end, with a few integration points (Gmail parsing edge cases, AI prompt tuning) left as clearly-marked extension points. Next up is hardening those edges and expanding the integration-test suite.',
            },
          ],
        },
      ],
    },
    no: {
      valueProp: 'Gmail-analyse og trygg masseopprydding, bygget som en ryddig Clean Architecture.',
      cardTeaser:
        'Gmail-analyse og trygg masseopprydding — Clean Architecture, krypterte OAuth-tokens, forhåndsvisning før sletting.',
      tldr: {
        what: 'Gmail-analyse, opprydding og avmeldingshåndtering med en bakgrunns-synk.',
        why: 'For å øve på Clean Architecture skikkelig og gjøre destruktive operasjoner trygge fra bunnen.',
        stack: '.NET 8 · PostgreSQL · React 18 · Gmail API · Serilog · Polly · Docker.',
        role: 'Eneste arkitekt og utvikler, fra ende til ende.',
      },
      sections: [
        {
          kind: 'problem',
          heading: 'Problem og kontekst',
          anchorId: 'problem',
          blocks: [
            {
              type: 'p',
              text: 'En travel innboks trenger analyse og opprydding, men masseoperasjoner på ekte e-post er farlige — ett feil filter kan slette ting du ikke får tilbake. Jeg bygde InboxIntel for å utforske to ting samtidig: en ryddig, testbar backend-arkitektur, og destruktive operasjoner som er trygge fra bunnen.',
            },
          ],
        },
        {
          kind: 'architecture',
          heading: 'Arkitektur',
          anchorId: 'arkitektur',
          blocks: [
            {
              type: 'p',
              text: 'En løsning med fire prosjekter i Clean Architecture bak en React-app. Avhengighetsregelen peker innover: Api → Infrastructure → Application → Domain. Kontrollerne har ingen forretningslogikk — de delegerer til tjenestegrensesnitt i Application-laget via DI. En bakgrunnstjeneste synkroniserer Gmail inn i PostgreSQL med Polly retry og backoff.',
            },
            {
              type: 'ul',
              items: [
                'Domain: entiteter og enums, uten eksterne avhengigheter.',
                'Application: tjenestegrensesnitt, DTO-er, validatorer og Gmail-søkeparser.',
                'Infrastructure: EF Core, Gmail-klient, synk-tjeneste, AI og eksport.',
                'Api: ASP.NET Core-kontrollere, auth, DI og Serilog — tynt med hensikt.',
              ],
            },
          ],
        },
        {
          kind: 'decisions',
          heading: 'Viktige valg og avveininger',
          anchorId: 'beslutninger',
          decisions: [
            {
              n: 1,
              choice: 'Full Clean Architecture over fire prosjekter.',
              alternative: 'Ett prosjekt hadde vært raskere å levere.',
              rationale:
                'Jeg ville at avhengighetsregelen skulle håndheves av prosjektstrukturen, ikke bare av disiplin. Det koster mer seremoni i starten og betaler seg i testbarhet og tydelige grenser.',
            },
            {
              n: 2,
              choice: 'Kryptere OAuth-refresh-tokens i ro og aldri logge dem.',
              alternative: 'Lagre dem som vanlige kolonner.',
              rationale:
                'Refresh-tokens er langlevde nøkler til noens innboks. De krypteres med ASP.NET Core Data Protection API (AES), med nøkler lagret på et montert volum — det viktigste sikkerhetsvalget i appen.',
            },
            {
              n: 3,
              choice: 'Alle destruktive handlinger er forhåndsvis-så-bekreft.',
              alternative: 'Slette umiddelbart ved forespørsel.',
              rationale:
                'All opprydding og avmelding krever en server-side forhåndsvisning og et eksplisitt Confirmed-flagg. AI-laget er kun rådgivende og kan aldri utløse en sletting.',
            },
          ],
        },
        {
          kind: 'security',
          heading: 'Sikkerhet og drift',
          anchorId: 'sikkerhet',
          blocks: [
            {
              type: 'ul',
              items: [
                'Gmail-scopes er kun lese/endre — send-scope blir aldri etterspurt.',
                'Polly gir retry og backoff mot Gmail-API-ets rategrenser og forbigående feil.',
                'FluentValidation på input; strukturert Serilog-logging som aldri lagrer tokens.',
                'Enhetstester dekker søkeparser og avmeldings-uttrekk; integrasjonstester starter API-verten og sjekker at autorisasjon håndheves.',
              ],
            },
          ],
        },
        {
          kind: 'screenshots',
          heading: 'Skjermbilder',
          anchorId: 'skjermbilder',
        },
        {
          kind: 'next',
          heading: 'Status og veien videre',
          anchorId: 'videre',
          blocks: [
            {
              type: 'p',
              text: 'InboxIntel er under aktiv utvikling: arkitekturen er komplett, lagene kompilerer og er koblet ende til ende, med noen integrasjonspunkter (kanttilfeller i Gmail-parsing, tuning av AI-prompter) igjen som tydelig markerte utvidelsespunkter. Neste steg er å herde disse kantene og utvide integrasjonstestene.',
            },
          ],
        },
      ],
    },
  },
};
