'use client'
import { useEffect, useState } from 'react'
import { useParams, useRouter } from 'next/navigation'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import {
  getSandbox, updateSandbox, deploySandboxService, deleteSandbox,
  listBranches, listRoutes, pushRoutes, listEnvironments,
  type Sandbox, type SandboxService, type Environment, type LiveRoute,
} from '@/lib/api'

export default function SandboxDetailClient() {
  const params = useParams<{ id: string }>()
  const id = params.id
  const router = useRouter()
  const [sb, setSb] = useState<Sandbox | null>(null)
  const [envs, setEnvs] = useState<Environment[]>([])
  const [routes, setRoutes] = useState<LiveRoute[]>([])
  const [routeBranch, setRouteBranch] = useState<string>('')
  const [error, setError] = useState<string | null>(null)
  const [busy, setBusy] = useState(false)
  const [creds, setCreds] = useState({ username: '', password: '' })
  const [newSvc, setNewSvc] = useState<{ repo: string; branch: string; hostPort: string; useOcp: boolean; envId: string }>({
    repo: '', branch: '', hostPort: '', useOcp: false, envId: '',
  })
  const [repoOptions, setRepoOptions] = useState<{ name: string; node: string }[]>([])

  async function refresh() {
    try {
      const s = await getSandbox(id)
      setSb(s)
    } catch (e) {
      setError(String(e))
    }
  }
  async function refreshRoutes() {
    try {
      const r = await listRoutes()
      const list: LiveRoute[] = []
      const overrides = r.overrides[id] ?? {}
      for (const [key, url] of Object.entries(r.routes)) {
        const ov = overrides[key]
        list.push({
          key,
          url,
          ocpDefault: r.defaults[key] ?? null,
          overridden: !!ov,
          sandboxId: ov ? id : undefined,
          overrideValue: ov ? ov.value : undefined,
          targetOcp: ov ? ov.targetOcp : undefined,
        })
      }
      list.sort((a, b) => a.key.localeCompare(b.key))
      setRoutes(list)
      setRouteBranch(r.branch)
    } catch (e) {
      setError(String(e))
    }
  }
  useEffect(() => {
    refresh()
    refreshRoutes()
    listEnvironments().then(setEnvs).catch(() => {})
    const base = (process.env.NEXT_PUBLIC_BASE_PATH ?? '').replace(/\/$/, '')
    fetch(`${base}/api/repos`, { credentials: 'include' })
      .then((r) => r.json())
      .then((arr: { name: string; node: string }[]) => setRepoOptions(arr))
      .catch(() => {})
  }, [id])

  if (!sb) {
    return <div className="container py-8">{error ? <p className="text-sm text-destructive">{error}</p> : <p className="text-sm text-muted-foreground">Loading…</p>}</div>
  }

  function updateService(idx: number, patch: Partial<SandboxService>) {
    setSb((cur) => {
      if (!cur) return cur
      const services = cur.services.slice()
      services[idx] = { ...services[idx], ...patch }
      return { ...cur, services }
    })
  }

  function addService() {
    if (!newSvc.repo) return
    setSb((cur) => {
      if (!cur) return cur
      return {
        ...cur,
        services: [
          ...cur.services,
          {
            id: `${cur.id}-${newSvc.repo}`,
            sandboxId: cur.id,
            repo: newSvc.repo,
            branch: newSvc.branch,
            hostPort: newSvc.hostPort ? Number(newSvc.hostPort) : 0,
            useOcp: newSvc.useOcp,
            envId: newSvc.envId || undefined,
          },
        ],
      }
    })
    setNewSvc({ repo: '', branch: '', hostPort: '', useOcp: false, envId: '' })
  }

  function removeService(idx: number) {
    setSb((cur) => {
      if (!cur) return cur
      const services = cur.services.slice()
      services.splice(idx, 1)
      return { ...cur, services }
    })
  }

  async function save() {
    if (!sb) return
    setBusy(true); setError(null)
    try {
      await updateSandbox(id, sb)
      await refresh()
    } catch (e) { setError(String(e)) } finally { setBusy(false) }
  }

  async function del() {
    if (!confirm('Delete this sandbox? Route overrides will be dropped.')) return
    setBusy(true)
    try {
      await deleteSandbox(id)
      router.push('/dashboard/sandboxes')
    } catch (e) { setError(String(e)) } finally { setBusy(false) }
  }

  async function deployService(svc: SandboxService) {
    if (!creds.username || !creds.password) {
      setError('enter Bitbucket credentials first')
      return
    }
    if (!svc.branch) {
      setError('set the branch first')
      return
    }
    setBusy(true); setError(null)
    try {
      await deploySandboxService(id, svc.repo, {
        branch: svc.branch,
        username: creds.username,
        password: creds.password,
        envId: svc.envId,
      })
      setTimeout(refreshRoutes, 1500)
    } catch (e) { setError(String(e)) } finally { setBusy(false) }
  }

  return (
    <div className="container py-8 space-y-6">
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-semibold tracking-tight">{sb.name}</h1>
          <p className="text-sm text-muted-foreground">
            Gateway: branch <span className="font-mono">{sb.gatewayBranch || '—'}</span> on port <span className="font-mono">{sb.gatewayHostPort || '—'}</span>
          </p>
        </div>
        <div className="flex gap-2">
          <Button variant="outline" onClick={save} disabled={busy}>Save</Button>
          <Button variant="outline" onClick={del} disabled={busy}>Delete</Button>
        </div>
      </div>

      {error && <p className="text-sm text-destructive">{error}</p>}

      <Card>
        <CardHeader>
          <CardTitle>Gateway</CardTitle>
          <CardDescription>The API gateway branch this sandbox runs. Switching it triggers a re-deploy + route re-apply.</CardDescription>
        </CardHeader>
        <CardContent className="grid gap-3 md:grid-cols-3">
          <div className="space-y-1.5">
            <Label>Branch</Label>
            <Input value={sb.gatewayBranch ?? ''} onChange={(e) => setSb({ ...sb, gatewayBranch: e.target.value })} placeholder="develop" />
          </div>
          <div className="space-y-1.5">
            <Label>Host port</Label>
            <Input value={sb.gatewayHostPort ?? 0} onChange={(e) => setSb({ ...sb, gatewayHostPort: Number(e.target.value) || 0 })} placeholder="8080" />
          </div>
          <div className="space-y-1.5">
            <Label>Env</Label>
            <select
              className="flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm"
              value={sb.gatewayEnvId ?? ''}
              onChange={(e) => setSb({ ...sb, gatewayEnvId: e.target.value || undefined })}
            >
              <option value="">— none —</option>
              {envs.map((e) => <option key={e.id} value={e.id}>{e.name}</option>)}
            </select>
          </div>
        </CardContent>
      </Card>

      <Card>
        <CardHeader>
          <div className="flex items-center justify-between">
            <div>
              <CardTitle>Routes (live from gateway config.php)</CardTitle>
              <CardDescription>
                {routeBranch ? <>Branch: <span className="font-mono">{routeBranch}</span></> : 'No deploy yet.'}
                {' · '}
                <button className="underline" onClick={refreshRoutes}>Refresh</button>
              </CardDescription>
            </div>
            <Badge variant="secondary">{routes.length} services</Badge>
          </div>
        </CardHeader>
        <CardContent>
          {routes.length === 0 ? (
            <p className="text-sm text-muted-foreground">
              No <code>{'<service>_url'}</code> lines in the current config.php. Deploy the gateway first.
            </p>
          ) : (
            <RouteTable
              routes={routes}
              onChange={async (key, value, targetOcp) => {
                setBusy(true); setError(null)
                try {
                  const existing = routes
                    .filter((r) => r.overridden && r.sandboxId === id && r.key !== key)
                    .map((r) => ({ key: r.key, value: r.url, targetOcp: false }))
                  const newOv = { key, value, targetOcp }
                  await pushRoutes(id, [...existing, newOv])
                  await refreshRoutes()
                } catch (e) { setError(String(e)) } finally { setBusy(false) }
              }}
              busy={busy}
            />
          )}
        </CardContent>
      </Card>

      <Card>
        <CardHeader>
          <CardTitle>Microservices</CardTitle>
          <CardDescription>Pick a branch, choose a host port, deploy. Use "use OCP" to leave the gateway's default URL in place.</CardDescription>
        </CardHeader>
        <CardContent className="space-y-4">
          {sb.services.length === 0 ? (
            <p className="text-sm text-muted-foreground">No services yet. Add one below.</p>
          ) : (
            sb.services.map((svc, idx) => (
              <div key={svc.id} className="rounded-md border p-3 space-y-2">
                <div className="flex items-center justify-between">
                  <div className="font-mono text-sm">{svc.repo}</div>
                  <div className="flex items-center gap-2">
                    <label className="text-xs flex items-center gap-1">
                      <input
                        type="checkbox"
                        checked={svc.useOcp}
                        onChange={(e) => updateService(idx, { useOcp: e.target.checked })}
                      />
                      use OCP
                    </label>
                    <Button size="sm" variant="outline" onClick={() => removeService(idx)}>Remove</Button>
                    <Button size="sm" onClick={() => deployService(svc)} disabled={busy || svc.useOcp}>Deploy</Button>
                  </div>
                </div>
                <div className="grid gap-2 md:grid-cols-4">
                  <div className="space-y-1.5">
                    <Label>Branch</Label>
                    <Input value={svc.branch ?? ''} onChange={(e) => updateService(idx, { branch: e.target.value })} placeholder="feature/login-error" />
                  </div>
                  <div className="space-y-1.5">
                    <Label>Host port</Label>
                    <Input type="number" value={svc.hostPort ?? 0} onChange={(e) => updateService(idx, { hostPort: Number(e.target.value) || 0 })} placeholder="9001" />
                  </div>
                  <div className="space-y-1.5">
                    <Label>Env</Label>
                    <select
                      className="flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm"
                      value={svc.envId ?? ''}
                      onChange={(e) => updateService(idx, { envId: e.target.value || undefined })}
                    >
                      <option value="">— none —</option>
                      {envs.map((e) => <option key={e.id} value={e.id}>{e.name}</option>)}
                    </select>
                  </div>
                  <div className="space-y-1.5">
                    <Label>Branches (cached)</Label>
                    <BranchPicker
                      repo={svc.repo}
                      value={svc.branch ?? ''}
                      onChange={(b) => updateService(idx, { branch: b })}
                    />
                  </div>
                </div>
              </div>
            ))
          )}

          <div className="rounded-md border border-dashed p-3 space-y-2">
            <div className="text-sm font-medium">Add a service</div>
            <div className="grid gap-2 md:grid-cols-5">
              <div className="space-y-1.5">
                <Label>Repo</Label>
                <select
                  className="flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm"
                  value={newSvc.repo}
                  onChange={(e) => setNewSvc({ ...newSvc, repo: e.target.value })}
                >
                  <option value="">— pick —</option>
                  {repoOptions.map((r) => <option key={r.name} value={r.name}>{r.name} ({r.node})</option>)}
                </select>
              </div>
              <div className="space-y-1.5 md:col-span-2">
                <Label>Branch</Label>
                <Input value={newSvc.branch} onChange={(e) => setNewSvc({ ...newSvc, branch: e.target.value })} placeholder="main" />
              </div>
              <div className="space-y-1.5">
                <Label>Host port</Label>
                <Input type="number" value={newSvc.hostPort} onChange={(e) => setNewSvc({ ...newSvc, hostPort: e.target.value })} placeholder="9001" />
              </div>
              <div className="space-y-1.5">
                <Label>Env</Label>
                <select
                  className="flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm"
                  value={newSvc.envId}
                  onChange={(e) => setNewSvc({ ...newSvc, envId: e.target.value })}
                >
                  <option value="">— none —</option>
                  {envs.map((e) => <option key={e.id} value={e.id}>{e.name}</option>)}
                </select>
              </div>
            </div>
            <Button size="sm" onClick={addService} disabled={!newSvc.repo || busy}>Add</Button>
          </div>
        </CardContent>
      </Card>

      <Card>
        <CardHeader>
          <CardTitle>Bitbucket credentials</CardTitle>
          <CardDescription>Used by every deploy from this page. Held in component state only.</CardDescription>
        </CardHeader>
        <CardContent className="grid gap-2 md:grid-cols-2">
          <div className="space-y-1.5">
            <Label>Username</Label>
            <Input value={creds.username} onChange={(e) => setCreds({ ...creds, username: e.target.value })} autoComplete="username" />
          </div>
          <div className="space-y-1.5">
            <Label>Password</Label>
            <Input type="password" value={creds.password} onChange={(e) => setCreds({ ...creds, password: e.target.value })} autoComplete="current-password" />
          </div>
        </CardContent>
      </Card>
    </div>
  )
}

function BranchPicker({ repo, value, onChange }: { repo: string; value: string; onChange: (b: string) => void }) {
  const [branches, setBranches] = useState<string[]>([])
  useEffect(() => {
    if (!repo) { setBranches([]); return }
    listBranches(repo).then(setBranches).catch(() => setBranches([]))
  }, [repo])
  if (branches.length === 0) return <Input value={value} onChange={(e) => onChange(e.target.value)} placeholder="(type a branch)" />
  return (
    <select
      className="flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm"
      value={value}
      onChange={(e) => onChange(e.target.value)}
    >
      <option value="">— pick —</option>
      {branches.map((b) => <option key={b} value={b}>{b}</option>)}
    </select>
  )
}

function RouteTable({
  routes, onChange, busy,
}: {
  routes: LiveRoute[]
  onChange: (key: string, value: string, targetOcp: boolean) => void
  busy: boolean
}) {
  const [editing, setEditing] = useState<Record<string, string>>({})
  return (
    <table className="w-full text-sm">
      <thead className="text-left text-xs text-muted-foreground">
        <tr>
          <th className="py-2 pr-3">Service</th>
          <th className="py-2 pr-3">Current URL</th>
          <th className="py-2 pr-3">OCP default</th>
          <th className="py-2 pr-3">Status</th>
          <th className="py-2 pr-3">Action</th>
        </tr>
      </thead>
      <tbody>
        {routes.map((r) => (
          <tr key={r.key} className="border-t">
            <td className="py-2 pr-3 font-mono">{r.key}</td>
            <td className="py-2 pr-3 font-mono text-xs">{r.url}</td>
            <td className="py-2 pr-3 font-mono text-xs text-muted-foreground">{r.ocpDefault ?? '—'}</td>
            <td className="py-2 pr-3">
              {r.overridden ? <Badge variant="warning">sandbox</Badge> : <Badge variant="secondary">OCP</Badge>}
            </td>
            <td className="py-2 pr-3">
              {r.overridden ? (
                <Button size="sm" variant="outline" disabled={busy} onClick={() => onChange(r.key, r.ocpDefault ?? '', true)}>
                  Restore OCP
                </Button>
              ) : (
                <div className="flex items-center gap-2">
                  <Input
                    className="h-8 w-56 font-mono text-xs"
                    placeholder={`http://172.18.136.92:9001`}
                    value={editing[r.key] ?? ''}
                    onChange={(e) => setEditing((cur) => ({ ...cur, [r.key]: e.target.value }))}
                  />
                  <Button
                    size="sm"
                    disabled={busy || !editing[r.key]}
                    onClick={() => {
                      onChange(r.key, editing[r.key], false)
                      setEditing((cur) => ({ ...cur, [r.key]: '' }))
                    }}
                  >
                    Take over
                  </Button>
                </div>
              )}
            </td>
          </tr>
        ))}
      </tbody>
    </table>
  )
}
