import Link from 'next/link'
import { createClient } from '@/lib/supabase/server'
import { getAppOrg } from '@/lib/org'
import { getEffectiveUser } from '@/lib/effective-user'
import { canTransfer } from '@/lib/permissions'
import { FilterBar, type FilterOptions } from '@/components/filter-bar'
import { fmtHoursMinutes, fmtUsd } from '@/lib/format'
import { SummaryTable, type ProjectRow } from './summary-table'

const TARGET_HOURS = 140

function parseYearMonth(s: string | undefined): { year: number; month: number } {
  const now = new Date()
  if (!s) return { year: now.getFullYear(), month: now.getMonth() + 1 }
  const m = /^(\d{4})-(\d{1,2})$/.exec(s)
  if (!m) return { year: now.getFullYear(), month: now.getMonth() + 1 }
  const y = Number(m[1])
  const mm = Number(m[2])
  if (mm < 1 || mm > 12) return { year: now.getFullYear(), month: now.getMonth() + 1 }
  return { year: y, month: mm }
}

function monthStart(year: number, month: number): string {
  return `${year.toString().padStart(4, '0')}-${month.toString().padStart(2, '0')}-01 00:00:00`
}

function nextMonthStart(year: number, month: number): string {
  const ny = month === 12 ? year + 1 : year
  const nm = month === 12 ? 1 : month + 1
  return monthStart(ny, nm)
}

function shiftMonth(year: number, month: number, delta: number): { year: number; month: number } {
  let m = month + delta
  let y = year
  while (m < 1) {
    m += 12
    y -= 1
  }
  while (m > 12) {
    m -= 12
    y += 1
  }
  return { year: y, month: m }
}

function monthLabel(year: number, month: number): string {
  return new Date(year, month - 1, 1).toLocaleDateString('en-US', {
    month: 'long',
    year: 'numeric',
  })
}

type ProjectRpcRow = {
  operator: string
  client: string
  project: string
  this_seconds: number
  prev_seconds: number
  all_seconds: number
  this_cost_usd: number | string
  prev_cost_usd: number | string
  all_cost_usd: number | string
  this_billout_usd: number | string
  prev_billout_usd: number | string
  all_billout_usd: number | string
  this_billout_adj_usd: number | string
  prev_billout_adj_usd: number | string
  all_billout_adj_usd: number | string
}

export default async function SummaryPage({
  searchParams,
}: {
  searchParams: Promise<Record<string, string | string[] | undefined>>
}) {
  const sp = await searchParams
  const monthParam = typeof sp.month === 'string' ? sp.month : undefined

  // Filter pivots (operator / client / user / source_email). Project is
  // intentionally absent — the table groups by project, so filtering by
  // it would just hide rows.
  const filterOperator =
    typeof sp.operator === 'string' && sp.operator.trim() !== ''
      ? sp.operator.trim()
      : null
  const filterClient =
    typeof sp.client === 'string' && sp.client.trim() !== ''
      ? sp.client.trim()
      : null
  const filterUser =
    typeof sp.user === 'string' && sp.user.trim() !== ''
      ? sp.user.trim()
      : null
  const filterSourceEmail =
    typeof sp.source_email === 'string' && sp.source_email.trim() !== ''
      ? sp.source_email.trim()
      : null

  const supabase = await createClient()
  const org = await getAppOrg(supabase)

  if (!org) {
    return (
      <main>
        <div className="page-head">
          <h1>Summary</h1>
        </div>
        <p className="error">Bowden Works organization not found.</p>
      </main>
    )
  }

  const current = parseYearMonth(monthParam)
  const previous = shiftMonth(current.year, current.month, -1)

  const thisStart = monthStart(current.year, current.month)
  const thisEnd = nextMonthStart(current.year, current.month)
  const prevStart = monthStart(previous.year, previous.month)
  const prevEnd = nextMonthStart(previous.year, previous.month)

  // View-as scoping: when viewing-as a non-owner, force the summary RPC to
  // only consider that user's imports. (Owner / super-admin in their normal
  // session: no scoping — they see everything.)
  const eu = await getEffectiveUser(supabase, org.id)
  const scopeToImportedBy =
    eu?.is_viewing_as &&
    !eu.is_super_admin &&
    eu.org_role !== 'owner'
      ? eu.effective_user_id
      : null

  // Run the project summary (with filters) AND the options-for-pivots
  // lookup in parallel. The options-RPC pulls distinct values within
  // the current filter scope so dropdowns narrow as you pick.
  const [projectsResult, optionsResult] = await Promise.all([
    supabase.rpc('summary_by_project', {
      p_org_id: org.id,
      p_this_start: thisStart,
      p_this_end: thisEnd,
      p_prev_start: prevStart,
      p_prev_end: prevEnd,
      p_imported_by: scopeToImportedBy,
      p_operator: filterOperator,
      p_client: filterClient,
      p_user: filterUser,
      p_source_email: filterSourceEmail,
    }),
    // Options for the FilterBar dropdowns: distinct operators / clients /
    // users / source_emails over ALL time (no date window) so the user
    // can pick across history. The existing entries_filter_options RPC
    // does the right thing — it already supports our pivots and the
    // imported_by gate.
    supabase.rpc('entries_filter_options', {
      p_org_id: org.id,
      p_start: null,
      p_end: null,
      p_status: 'all',
      p_batch: null,
      p_q: null,
      p_project: null,
      p_user: filterUser,
      p_source_email: filterSourceEmail,
      p_client: filterClient,
      p_operator: filterOperator,
      p_imported_by: scopeToImportedBy,
    }),
  ])

  const projectRows = (projectsResult.data as ProjectRpcRow[] | null) ?? []

  // FilterBar options. The RPC returns the same shape as /entries.
  type OptionsRow = {
    operators: string[] | null
    clients: string[] | null
    projects: string[] | null
    users: string[] | null
    source_emails: string[] | null
  }
  const optionsRow = (optionsResult.data as OptionsRow[] | null)?.[0]
  const filterOptions: FilterOptions = {
    operators: optionsRow?.operators ?? [],
    clients: optionsRow?.clients ?? [],
    projects: optionsRow?.projects ?? [],
    users: optionsRow?.users ?? [],
    source_emails: optionsRow?.source_emails ?? [],
  }
  const rpcError = projectsResult.error

  const totals = projectRows.reduce(
    (acc, r) => ({
      this_seconds: acc.this_seconds + Number(r.this_seconds ?? 0),
      prev_seconds: acc.prev_seconds + Number(r.prev_seconds ?? 0),
      all_seconds: acc.all_seconds + Number(r.all_seconds ?? 0),
      this_cost: acc.this_cost + Number(r.this_cost_usd ?? 0),
      prev_cost: acc.prev_cost + Number(r.prev_cost_usd ?? 0),
      all_cost: acc.all_cost + Number(r.all_cost_usd ?? 0),
      this_billout: acc.this_billout + Number(r.this_billout_usd ?? 0),
      prev_billout: acc.prev_billout + Number(r.prev_billout_usd ?? 0),
      all_billout: acc.all_billout + Number(r.all_billout_usd ?? 0),
      // Adjusted billout (pct + fixed already applied per row by the RPC).
      this_billout_adj:
        acc.this_billout_adj + Number(r.this_billout_adj_usd ?? 0),
      prev_billout_adj:
        acc.prev_billout_adj + Number(r.prev_billout_adj_usd ?? 0),
      all_billout_adj:
        acc.all_billout_adj + Number(r.all_billout_adj_usd ?? 0),
    }),
    {
      this_seconds: 0,
      prev_seconds: 0,
      all_seconds: 0,
      this_cost: 0,
      prev_cost: 0,
      all_cost: 0,
      this_billout: 0,
      prev_billout: 0,
      all_billout: 0,
      this_billout_adj: 0,
      prev_billout_adj: 0,
      all_billout_adj: 0,
    },
  )

  // Owner-only flag: gates the billout numbers on the headline card and
  // the per-row stacked rendering in SummaryTable.
  const canSeeBillout = canTransfer(eu)

  const projectTableRows: ProjectRow[] = projectRows
    .map((r) => ({
      operator: r.operator,
      client: r.client,
      project: r.project,
      prevSeconds: Number(r.prev_seconds ?? 0),
      thisSeconds: Number(r.this_seconds ?? 0),
      allSeconds: Number(r.all_seconds ?? 0),
      prevCost: Number(r.prev_cost_usd ?? 0),
      thisCost: Number(r.this_cost_usd ?? 0),
      allCost: Number(r.all_cost_usd ?? 0),
      prevBillout: Number(r.prev_billout_adj_usd ?? r.prev_billout_usd ?? 0),
      thisBillout: Number(r.this_billout_adj_usd ?? r.this_billout_usd ?? 0),
      allBillout: Number(r.all_billout_adj_usd ?? r.all_billout_usd ?? 0),
    }))
    // Hide rows with no activity in the prev/this windows.
    .filter((r) => r.prevSeconds > 0 || r.thisSeconds > 0)

  const totalHrs = totals.this_seconds / 3600
  const overUnder = totalHrs - TARGET_HOURS
  const overUnderClass = overUnder >= 0 ? 'over-target' : 'under-target'

  const monthFmt = (y: number, m: number) =>
    `${y.toString().padStart(4, '0')}-${m.toString().padStart(2, '0')}`

  return (
    <main>
      <div className="page-head">
        <div>
          <h1>{monthLabel(current.year, current.month)}</h1>
          <p className="subtitle">
            Billout cost and hours. Cost is locked to each entry&apos;s
            import-time base rate — changing a team rate later only
            affects new imports.
          </p>
        </div>
        <div className="page-head-actions">
          <Link
            href={(() => {
              // Preserve filter pivots when paging through months.
              const next = new URLSearchParams()
              for (const [k, v] of Object.entries(sp)) {
                if (typeof v === 'string') next.set(k, v)
              }
              next.set('month', monthFmt(previous.year, previous.month))
              return `/?${next.toString()}`
            })()}
            className="button-link-secondary"
          >
            ← {monthLabel(previous.year, previous.month)}
          </Link>
          <Link
            href={(() => {
              const next = new URLSearchParams()
              for (const [k, v] of Object.entries(sp)) {
                if (typeof v === 'string' && k !== 'month') next.set(k, v)
              }
              const qs = next.toString()
              return qs ? `/?${qs}` : '/'
            })()}
            className="button-link-secondary"
          >
            This month
          </Link>
        </div>
      </div>

      {rpcError && <p className="error">{rpcError.message}</p>}

      <div className="panel summary-headline">
        {canSeeBillout ? (
          <span style={{ display: 'flex', flexDirection: 'column', gap: '0.1rem' }}>
            <span
              className="summary-cost"
              style={{ color: '#0a7d3f' }}
              title={
                totals.this_billout === totals.this_billout_adj
                  ? "Owner-only: what we charge the client for this month's billout hours."
                  : `Adjusted billout (raw ${fmtUsd(totals.this_billout)} after per-project adjustments).`
              }
            >
              {fmtUsd(totals.this_billout_adj)}
            </span>
            <span
              className="muted"
              style={{ fontSize: '0.85em' }}
              title="Cost (what we pay) for this month's billout hours."
            >
              {fmtUsd(totals.this_cost)} cost
            </span>
          </span>
        ) : (
          <span className="summary-cost">{fmtUsd(totals.this_cost)}</span>
        )}
        <span className="summary-hours">{fmtHoursMinutes(totals.this_seconds)} hours</span>
        <span className={`summary-target ${overUnderClass}`}>
          {overUnder >= 0 ? '+' : ''}
          {overUnder.toFixed(2)}h vs {TARGET_HOURS}h target
        </span>
      </div>

      <FilterBar
        showPivots
        hideDate
        hideProjectPivot
        showClear
        options={filterOptions}
      />

      <div className="panel" style={{ padding: 0, overflow: 'hidden' }}>
        <div style={{ padding: '1rem 1.25rem 0.5rem' }}>
          <h2 style={{ margin: 0, fontSize: '1.05rem' }}>By project</h2>
          <p
            className="muted"
            style={{ fontSize: '0.85em', margin: '0.25rem 0 0' }}
          >
            Click any column header to re-sort.
          </p>
        </div>
        <SummaryTable
          rows={projectTableRows}
          totals={{
            prevSeconds: totals.prev_seconds,
            thisSeconds: totals.this_seconds,
            allSeconds: totals.all_seconds,
            prevCost: totals.prev_cost,
            thisCost: totals.this_cost,
            allCost: totals.all_cost,
            prevBillout: totals.prev_billout_adj,
            thisBillout: totals.this_billout_adj,
            allBillout: totals.all_billout_adj,
          }}
          labels={{
            prev: monthLabel(previous.year, previous.month),
            this: monthLabel(current.year, current.month),
          }}
          canSeeBillout={canSeeBillout}
        />
      </div>

      <div className="panel">
        <p className="muted" style={{ margin: 0, fontSize: '0.9em' }}>
          Want the same view sliced by team member, source email, or project?
          Head to <Link href="/entries">Entries</Link> and use the filter
          row at the top — the totals card mirrors whatever you filter.
        </p>
      </div>
    </main>
  )
}
