/**
 * Main-process gitea bridge. All gitea traffic runs here — the token never
 * reaches the renderer (which is CSP-locked to 'self' anyway). The renderer
 * calls these over IPC (see preload). Config for the dogfood slice comes from
 * the environment or the repo's .env.local; Settings/Onboarding wire it up
 * properly later.
 */

import { readFileSync } from 'node:fs'
import { dirname, join } from 'node:path'

import { createGiteaClient, type GiteaConfig } from '@commitea/core'
import { ipcMain } from 'electron'

/** Walk up from cwd looking for a .env.local with a GITEA_TOKEN (dev convenience). */
function loadEnvLocalToken(): string | undefined {
  let dir = process.cwd()
  for (let i = 0; i < 6; i++) {
    try {
      const txt = readFileSync(join(dir, '.env.local'), 'utf8')
      const m = /^GITEA_TOKEN\s*=\s*(.+?)\s*$/m.exec(txt)
      if (m) return m[1].trim()
    } catch {
      // not in this dir — keep walking up
    }
    const parent = dirname(dir)
    if (parent === dir) break
    dir = parent
  }
  return undefined
}

function resolveConfig(): GiteaConfig | null {
  // E2E runs against fixtures — never hit the network from the test harness.
  if (process.env.COMMITEA_E2E === '1') return null
  const token = process.env.GITEA_TOKEN ?? loadEnvLocalToken()
  if (!token) return null
  return {
    baseUrl: process.env.GITEA_BASE_URL ?? 'https://gitea.stephenmann.io',
    token,
    owner: process.env.GITEA_OWNER ?? 'christian',
    repo: process.env.GITEA_REPO ?? 'commitea',
  }
}

export function registerGiteaIpc(): void {
  const config = resolveConfig()
  const client = config ? createGiteaClient(config, fetch) : null
  const repo = config ? `${config.owner}/${config.repo}` : null

  ipcMain.handle('gitea:status', () => ({ configured: !!config, repo }))

  ipcMain.handle('gitea:reconcile', async () => {
    if (!client) return { configured: false, issues: [], milestones: [], deps: [] }
    const [issues, milestones] = await Promise.all([client.listIssues(), client.listMilestones()])
    // dependency edges among the open scope (the scheduler only plans what's left)
    const open = issues.filter((i) => i.state === 'open')
    const perIssue = await Promise.all(
      open.map(async (i) => ({ issue: i.number, dependsOn: await client.getIssueDependencies(i.number) })),
    )
    const deps = perIssue.flatMap(({ issue, dependsOn }) => dependsOn.map((d) => ({ issue, dependsOn: d })))
    return { configured: true, issues, milestones, deps }
  })

  ipcMain.handle('gitea:getIssue', async (_event, index: number) => {
    if (!client) return null
    return client.getIssue(index)
  })
}
