import { useCallback, useEffect, useState } from 'react'
import { ArrowRight, Check, GitBranch, Plus, Workflow } from 'lucide-react'
import { toast } from 'sonner'
import { AppShell } from '@/components/AppShell'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Card, CardContent } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'
import {
  Sheet,
  SheetContent,
  SheetDescription,
  SheetHeader,
  SheetTitle,
} from '@/components/ui/sheet'
import { Textarea } from '@/components/ui/textarea'
import { api } from '@/lib/api'
import { useAuth } from '@/store/auth'

interface Division {
  id: string
  name: string
}

interface ChangeSummary {
  id: string
  customerName: string
  title: string
  status: string
  estimateHours: number | null
  amount: number | null
  currency: string
  stepCount: number
  doneStepCount: number
}

interface ChangeStep {
  id: string
  divisionId: string | null
  divisionName: string | null
  title: string
  estimateHours: number
  status: string
  dependsOnStepId: string | null
  order: number
}

interface ChangeDetail {
  summary: ChangeSummary
  description: string | null
  totalStepHours: number
  steps: ChangeStep[]
}

const STAGES = ['Requested', 'Estimated', 'Approved', 'Paid', 'Live'] as const
const STEP_STATUSES = ['Pending', 'InProgress', 'Done', 'Blocked'] as const

// The single commercial action available at each pipeline stage.
const ACTION: Record<string, { label: string; path: string } | null> = {
  Requested: { label: 'Send estimate', path: 'estimate' },
  Estimated: { label: 'Mark approved', path: 'approve' },
  Approved: { label: 'Record payment', path: 'pay' },
  Paid: { label: 'Go live', path: 'go-live' },
  Live: null,
  Rejected: null,
}

const STATUS_TONE: Record<string, string> = {
  Requested: 'bg-muted text-muted-foreground',
  Estimated: 'bg-sky-500/15 text-sky-700 dark:text-sky-400',
  Approved: 'bg-violet-500/15 text-violet-700 dark:text-violet-400',
  Paid: 'bg-amber-500/15 text-amber-700 dark:text-amber-400',
  Live: 'bg-emerald-500/15 text-emerald-700 dark:text-emerald-400',
  Rejected: 'bg-destructive/15 text-destructive',
}

export function PipelinePage() {
  const organizationId = useAuth((s) => s.organizationId)
  const [requests, setRequests] = useState<ChangeSummary[]>([])
  const [divisions, setDivisions] = useState<Division[]>([])
  const [openId, setOpenId] = useState<string | null>(null)
  const [creating, setCreating] = useState(false)

  const load = useCallback(async () => {
    if (!organizationId) return
    try {
      const [list, divs] = await Promise.all([
        api.get<ChangeSummary[]>(`/api/orgboard/change-requests?organizationId=${organizationId}`),
        api.get<Division[]>(`/api/orgboard/divisions?organizationId=${organizationId}`).catch(() => []),
      ])
      setRequests(list)
      setDivisions(divs)
    } catch (err) {
      toast.error((err as Error).message)
    }
  }, [organizationId])

  useEffect(() => {
    void load()
  }, [load])

  return (
    <AppShell>
      <div className="mx-auto max-w-4xl p-6">
        <header className="mb-5 flex items-center justify-between gap-4">
          <div>
            <h1 className="flex items-center gap-2 text-2xl font-semibold tracking-tight">
              <Workflow className="size-6" /> Delivery pipeline
            </h1>
            <p className="text-sm text-muted-foreground">
              Customer change requests across divisions: estimate → approve → pay → go-live.
            </p>
          </div>
          <Button size="sm" onClick={() => setCreating((v) => !v)}>
            <Plus data-icon="inline-start" /> New request
          </Button>
        </header>

        {creating && organizationId && (
          <NewRequestForm
            organizationId={organizationId}
            onCreated={() => {
              setCreating(false)
              void load()
            }}
          />
        )}

        {/* Pipeline legend */}
        <div className="mb-5 flex flex-wrap items-center gap-1.5 text-xs text-muted-foreground">
          {STAGES.map((s, i) => (
            <span key={s} className="flex items-center gap-1.5">
              <span className="rounded-full bg-muted px-2 py-0.5 font-medium">{s}</span>
              {i < STAGES.length - 1 && <ArrowRight className="size-3" />}
            </span>
          ))}
        </div>

        <div className="flex flex-col gap-2">
          {requests.map((cr) => {
            const pct = cr.stepCount > 0 ? Math.round((cr.doneStepCount / cr.stepCount) * 100) : 0
            return (
              <button
                key={cr.id}
                type="button"
                onClick={() => setOpenId(cr.id)}
                className="flex items-center gap-3 rounded-xl border bg-card/60 px-4 py-3 text-left backdrop-blur-sm transition-colors hover:border-ring/60"
              >
                <div className="min-w-0 flex-1">
                  <div className="flex items-center gap-2">
                    <span className="truncate font-medium">{cr.title}</span>
                    <span className={`shrink-0 rounded-md px-2 py-0.5 text-xs font-medium ${STATUS_TONE[cr.status] ?? 'bg-muted'}`}>
                      {cr.status}
                    </span>
                  </div>
                  <p className="truncate text-xs text-muted-foreground">
                    {cr.customerName}
                    {cr.estimateHours != null && ` · ${cr.estimateHours}h`}
                    {cr.amount != null && ` · ${cr.amount.toLocaleString()} ${cr.currency}`}
                    {cr.stepCount > 0 && ` · ${cr.doneStepCount}/${cr.stepCount} steps`}
                  </p>
                </div>
                {cr.stepCount > 0 && (
                  <div className="hidden h-2 w-24 shrink-0 overflow-hidden rounded-full bg-muted/60 sm:block">
                    <div className="h-full rounded-full bg-emerald-500 transition-all" style={{ width: `${pct}%` }} />
                  </div>
                )}
              </button>
            )
          })}
          {requests.length === 0 && (
            <Card>
              <CardContent className="py-10 text-center text-sm text-muted-foreground">
                No change requests yet. Log a customer ask to start the pipeline.
              </CardContent>
            </Card>
          )}
        </div>
      </div>

      {openId && (
        <RequestDrawer
          id={openId}
          divisions={divisions}
          onClose={() => setOpenId(null)}
          onChanged={load}
        />
      )}
    </AppShell>
  )
}

function NewRequestForm({ organizationId, onCreated }: { organizationId: string; onCreated: () => void }) {
  const [customer, setCustomer] = useState('')
  const [title, setTitle] = useState('')
  const [description, setDescription] = useState('')
  const [busy, setBusy] = useState(false)

  async function submit() {
    if (!customer.trim() || !title.trim()) {
      toast.error('Customer and title are required.')
      return
    }
    setBusy(true)
    try {
      await api.post('/api/orgboard/change-requests', { organizationId, customerName: customer, title, description })
      toast.success('Change request logged.')
      onCreated()
    } catch (err) {
      toast.error((err as Error).message)
    } finally {
      setBusy(false)
    }
  }

  return (
    <div className="mb-5 flex flex-col gap-3 rounded-xl border bg-card/60 p-4 backdrop-blur-sm">
      <div className="grid gap-3 sm:grid-cols-2">
        <div className="flex flex-col gap-1.5">
          <Label>Customer</Label>
          <Input value={customer} onChange={(e) => setCustomer(e.target.value)} placeholder="Acme Corp" />
        </div>
        <div className="flex flex-col gap-1.5">
          <Label>Title</Label>
          <Input value={title} onChange={(e) => setTitle(e.target.value)} placeholder="Add SSO to the portal" />
        </div>
      </div>
      <div className="flex flex-col gap-1.5">
        <Label>What they're asking for</Label>
        <Textarea value={description} onChange={(e) => setDescription(e.target.value)} rows={3} />
      </div>
      <div className="flex justify-end">
        <Button size="sm" disabled={busy} onClick={submit}>Log request</Button>
      </div>
    </div>
  )
}

function RequestDrawer({
  id,
  divisions,
  onClose,
  onChanged,
}: {
  id: string
  divisions: Division[]
  onClose: () => void
  onChanged: () => void
}) {
  const [detail, setDetail] = useState<ChangeDetail | null>(null)
  const [busy, setBusy] = useState(false)
  const [amount, setAmount] = useState('')
  const [currency, setCurrency] = useState('USD')

  const reload = useCallback(async () => {
    try {
      setDetail(await api.get<ChangeDetail>(`/api/orgboard/change-requests/${id}`))
    } catch (err) {
      toast.error((err as Error).message)
    }
  }, [id])

  useEffect(() => {
    void reload()
  }, [reload])

  async function act(fn: () => Promise<ChangeDetail>, success?: string) {
    setBusy(true)
    try {
      setDetail(await fn())
      if (success) toast.success(success)
      onChanged()
    } catch (err) {
      toast.error((err as Error).message)
    } finally {
      setBusy(false)
    }
  }

  const status = detail?.summary.status ?? 'Requested'
  const action = ACTION[status]
  const stageIndex = STAGES.indexOf(status as (typeof STAGES)[number])

  return (
    <Sheet open onOpenChange={(open) => !open && onClose()}>
      <SheetContent className="overflow-y-auto sm:max-w-xl">
        {detail && (
          <>
            <SheetHeader>
              <div className="flex items-center gap-2">
                <span className={`rounded-md px-2 py-0.5 text-xs font-medium ${STATUS_TONE[status] ?? 'bg-muted'}`}>{status}</span>
                <Badge variant="outline">{detail.summary.customerName}</Badge>
              </div>
              <SheetTitle>{detail.summary.title}</SheetTitle>
              {detail.description && <SheetDescription>{detail.description}</SheetDescription>}
            </SheetHeader>

            {/* Stage stepper */}
            <div className="flex items-center gap-1 px-4">
              {STAGES.map((s, i) => {
                const done = stageIndex >= 0 && i <= stageIndex
                return (
                  <div key={s} className="flex flex-1 flex-col items-center gap-1">
                    <div className="flex w-full items-center">
                      <span className={`grid size-6 shrink-0 place-items-center rounded-full border text-[10px] ${done ? 'border-emerald-500 bg-emerald-500/15 text-emerald-600' : 'border-border bg-muted/40 text-muted-foreground'}`}>
                        {done ? <Check className="size-3" /> : i + 1}
                      </span>
                      {i < STAGES.length - 1 && <span className={`h-0.5 flex-1 ${stageIndex > i ? 'bg-emerald-500' : 'bg-border'}`} />}
                    </div>
                    <span className="text-[10px] text-muted-foreground">{s}</span>
                  </div>
                )
              })}
            </div>

            {/* Totals + commercial action */}
            <div className="mx-4 flex flex-col gap-3 rounded-xl border bg-card/60 p-4 backdrop-blur-sm">
              <div className="flex items-center justify-between text-sm">
                <span className="text-muted-foreground">Total estimate</span>
                <span className="font-semibold">{detail.totalStepHours}h{detail.summary.amount != null && ` · ${detail.summary.amount.toLocaleString()} ${detail.summary.currency}`}</span>
              </div>

              {status === 'Requested' && (
                <div className="flex items-end gap-2">
                  <div className="flex flex-1 flex-col gap-1">
                    <Label className="text-xs">Quote amount (optional)</Label>
                    <Input value={amount} onChange={(e) => setAmount(e.target.value)} inputMode="decimal" placeholder="12000" />
                  </div>
                  <div className="flex w-24 flex-col gap-1">
                    <Label className="text-xs">Currency</Label>
                    <Input value={currency} onChange={(e) => setCurrency(e.target.value)} />
                  </div>
                </div>
              )}

              {action && (
                <Button
                  disabled={busy}
                  onClick={() =>
                    act(
                      () =>
                        api.post<ChangeDetail>(`/api/orgboard/change-requests/${id}/${action.path}`,
                          action.path === 'estimate'
                            ? { amount: amount ? Number(amount) : null, currency }
                            : {}),
                      `${action.label} done.`,
                    )
                  }
                >
                  {action.label} <ArrowRight data-icon="inline-end" />
                </Button>
              )}
              {status !== 'Live' && status !== 'Rejected' && (
                <Button
                  variant="ghost"
                  size="sm"
                  disabled={busy}
                  className="text-destructive hover:text-destructive"
                  onClick={() => act(() => api.post<ChangeDetail>(`/api/orgboard/change-requests/${id}/reject`, {}), 'Rejected.')}
                >
                  Reject request
                </Button>
              )}
            </div>

            {/* Steps */}
            <div className="flex flex-col gap-2 px-4 pb-6">
              <Label className="flex items-center gap-1.5"><GitBranch className="size-4" /> Cross-division steps</Label>
              {detail.steps.map((step) => (
                <div key={step.id} className="flex items-center gap-2 rounded-lg border bg-card/50 px-3 py-2 text-sm backdrop-blur-sm">
                  <div className="min-w-0 flex-1">
                    <p className="truncate font-medium">{step.title}</p>
                    <p className="text-xs text-muted-foreground">
                      {step.divisionName ?? 'Unassigned'} · {step.estimateHours}h
                      {step.dependsOnStepId && ' · depends on a prior step'}
                    </p>
                  </div>
                  <Select value={step.status} onValueChange={(v) => act(() => api.patch<ChangeDetail>(`/api/orgboard/change-requests/${id}/steps/${step.id}`, { status: v }))}>
                    <SelectTrigger className="h-8 w-32 text-xs"><SelectValue /></SelectTrigger>
                    <SelectContent>
                      <SelectGroup>
                        {STEP_STATUSES.map((s) => <SelectItem key={s} value={s}>{s}</SelectItem>)}
                      </SelectGroup>
                    </SelectContent>
                  </Select>
                </div>
              ))}
              {detail.steps.length === 0 && <p className="text-xs text-muted-foreground">No steps yet — break the work down by division below.</p>}

              <AddStepForm id={id} divisions={divisions} steps={detail.steps} onAdded={(d) => setDetail(d)} />
            </div>
          </>
        )}
      </SheetContent>
    </Sheet>
  )
}

function AddStepForm({
  id,
  divisions,
  steps,
  onAdded,
}: {
  id: string
  divisions: Division[]
  steps: ChangeStep[]
  onAdded: (detail: ChangeDetail) => void
}) {
  const [title, setTitle] = useState('')
  const [hours, setHours] = useState('')
  const [divisionId, setDivisionId] = useState<string>('')
  const [dependsOn, setDependsOn] = useState<string>('')
  const [busy, setBusy] = useState(false)

  async function submit() {
    if (!title.trim() || !hours) {
      toast.error('Step title and hours are required.')
      return
    }
    setBusy(true)
    try {
      const detail = await api.post<ChangeDetail>(`/api/orgboard/change-requests/${id}/steps`, {
        title,
        estimateHours: Number(hours),
        divisionId: divisionId || null,
        dependsOnStepId: dependsOn || null,
      })
      onAdded(detail)
      setTitle('')
      setHours('')
      setDivisionId('')
      setDependsOn('')
    } catch (err) {
      toast.error((err as Error).message)
    } finally {
      setBusy(false)
    }
  }

  return (
    <div className="mt-2 flex flex-col gap-2 rounded-lg border border-dashed p-3">
      <div className="flex gap-2">
        <Input value={title} onChange={(e) => setTitle(e.target.value)} placeholder="Step (e.g. Build SSO connector)" className="flex-1" />
        <Input value={hours} onChange={(e) => setHours(e.target.value)} inputMode="decimal" placeholder="Hours" className="w-24" />
      </div>
      <div className="flex gap-2">
        <Select value={divisionId} onValueChange={setDivisionId}>
          <SelectTrigger className="flex-1"><SelectValue placeholder="Division (optional)" /></SelectTrigger>
          <SelectContent>
            <SelectGroup>
              {divisions.map((d) => <SelectItem key={d.id} value={d.id}>{d.name}</SelectItem>)}
            </SelectGroup>
          </SelectContent>
        </Select>
        {steps.length > 0 && (
          <Select value={dependsOn} onValueChange={setDependsOn}>
            <SelectTrigger className="flex-1"><SelectValue placeholder="Depends on (optional)" /></SelectTrigger>
            <SelectContent>
              <SelectGroup>
                {steps.map((s) => <SelectItem key={s.id} value={s.id}>{s.title}</SelectItem>)}
              </SelectGroup>
            </SelectContent>
          </Select>
        )}
      </div>
      <div className="flex justify-end">
        <Button size="sm" variant="outline" disabled={busy} onClick={submit}>
          <Plus data-icon="inline-start" /> Add step
        </Button>
      </div>
    </div>
  )
}
