"use client";

import { useState, useTransition } from "react";
import { useRouter } from "next/navigation";
import { Button, Card } from "@/components/ui";
import { Field, inputClass } from "@/components/ui/form";
import { addDomainAction, assignMemberAction, createOrganizationAction, createSiteAction, removeDomainAction, removeMemberAction, setOrganizationStatusAction, setPrimaryDomainAction, updateDomainAction } from "@/lib/actions/organizations";
import type { ActionResult } from "@/lib/actions/result";

type Msg = { ok: boolean; text: string } | null;
function useRun() {
  const router = useRouter();
  const [pending, start] = useTransition();
  const [msg, setMsg] = useState<Msg>(null);
  const [errors, setErrors] = useState<Record<string, string>>({});
  const run = (fn: () => Promise<ActionResult | void>, onOk?: () => void) => {
    setMsg(null); setErrors({});
    start(async () => {
      const r = await fn();
      if (r && !r.ok) { setErrors(r.fieldErrors ?? {}); setMsg({ ok: false, text: r.error }); }
      else if (r) { setMsg({ ok: true, text: r.message ?? "Done" }); onOk?.(); router.refresh(); }
    });
  };
  return { pending, msg, errors, run };
}
const Status = ({ msg }: { msg: Msg }) => <p role="status" aria-live="polite" className={msg ? (msg.ok ? "text-sm text-success" : "text-sm text-danger") : "sr-only"}>{msg?.text}</p>;

export function NewOrganization() {
  const { pending, msg, errors, run } = useRun();
  const [name, setName] = useState("");
  return (
    <Card className="mb-4 p-4">
      <h2 className="mb-3 text-sm font-semibold">New organization</h2>
      <div className="grid gap-3 sm:grid-cols-[1fr_auto] sm:items-end">
        <Field id="no-name" label="Name" error={errors.name}><input id="no-name" className={inputClass} maxLength={120} value={name} onChange={(e) => setName(e.target.value)} /></Field>
        <Button disabled={pending || name.trim().length < 2} onClick={() => run(() => createOrganizationAction({ name }))}>Create</Button>
      </div>
      <Status msg={msg} />
    </Card>
  );
}

export function StatusPanel({ orgId, status }: { orgId: string; status: string }) {
  const { pending, msg, run } = useRun();
  const [confirm, setConfirm] = useState<string | null>(null);
  const options = (["ACTIVE", "SUSPENDED", "ARCHIVED"] as const).filter((s) => s !== status);
  return (
    <Card className="space-y-3 p-4">
      <h2 className="text-sm font-semibold">Organization status</h2>
      <p className="text-sm text-muted-foreground">Suspended or archived organizations lose access immediately: their members cannot sign in to its sites and its websites stop being served. Nothing is deleted.</p>
      <div className="flex flex-wrap gap-2">
        {options.map((s) => confirm === s ? (
          <Button key={s} variant="danger" disabled={pending} onClick={() => run(() => setOrganizationStatusAction(orgId, s), () => setConfirm(null))}>Confirm {s.toLowerCase()}</Button>
        ) : (
          <Button key={s} variant="secondary" disabled={pending} onClick={() => (s === "ACTIVE" ? run(() => setOrganizationStatusAction(orgId, s)) : setConfirm(s))}>{s === "ACTIVE" ? "Reactivate" : s === "SUSPENDED" ? "Suspend" : "Archive"}</Button>
        ))}
        {confirm ? <Button variant="ghost" onClick={() => setConfirm(null)}>Cancel</Button> : null}
      </div>
      <Status msg={msg} />
    </Card>
  );
}

export function NewSite({ orgId, disabled }: { orgId: string; disabled: boolean }) {
  const { pending, msg, errors, run } = useRun();
  const [v, setV] = useState({ name: "", hostname: "", timezone: "UTC" });
  const set = (p: Partial<typeof v>) => setV((x) => ({ ...x, ...p }));
  return (
    <Card className="space-y-3 p-4">
      <h2 className="text-sm font-semibold">Add a website</h2>
      <div className="grid gap-3 sm:grid-cols-2">
        <Field id="ns-name" label="Name" error={errors.name}><input id="ns-name" className={inputClass} disabled={disabled} value={v.name} onChange={(e) => set({ name: e.target.value })} /></Field>
        <Field id="ns-host" label="Primary domain" error={errors.hostname}><input id="ns-host" className={inputClass} disabled={disabled} placeholder="www.example.com" value={v.hostname} onChange={(e) => set({ hostname: e.target.value })} /></Field>
        <Field id="ns-tz" label="Time zone" error={errors.timezone}><input id="ns-tz" className={inputClass} disabled={disabled} placeholder="Europe/London" value={v.timezone} onChange={(e) => set({ timezone: e.target.value })} /></Field>
      </div>
      <Button disabled={pending || disabled || !v.name || !v.hostname} onClick={() => run(() => createSiteAction(orgId, v), () => setV({ name: "", hostname: "", timezone: "UTC" }))}>Create website</Button>
      <p className="text-xs text-muted-foreground">Point the domain’s DNS at this platform separately; the platform does not verify ownership of the domain.</p>
      <Status msg={msg} />
    </Card>
  );
}

export interface AccessRow { id: string; userId: string; name: string; email: string; roleKey: string; roleName: string; website: string }
export interface MemberOptions {
  users: { id: string; name: string; email: string }[];
  roles: { key: string; name: string; description: string; siteScoped: boolean }[];
  sites: { id: string; name: string }[];
}

/** Who has which access in this organization: pick a user and a role (and a website for site-level roles). */
export function MembersPanel({ orgId, access, options }: { orgId: string; access: AccessRow[]; options: MemberOptions }) {
  const { pending, msg, errors, run } = useRun();
  const [userId, setUserId] = useState("");
  const [roleKey, setRoleKey] = useState(options.roles[0]?.key ?? "");
  const [siteId, setSiteId] = useState("all");
  const role = options.roles.find((r) => r.key === roleKey);
  return (
    <Card className="space-y-3 p-4">
      <h2 className="text-sm font-semibold">Members &amp; access</h2>
      <ul className="divide-y divide-border text-sm">
        {access.map((a) => (
          <li key={a.id} className="flex flex-wrap items-center justify-between gap-2 py-2">
            <span>{a.name} <span className="text-muted-foreground">({a.email})</span><span className="block text-xs text-muted-foreground">{a.roleName} · {a.website}</span></span>
            <Button variant="ghost" disabled={pending} aria-label={`Remove ${a.name} as ${a.roleName} (${a.website})`} onClick={() => run(() => removeMemberAction(orgId, a.id))}>Remove</Button>
          </li>
        ))}
        {access.length === 0 ? <li className="py-2 text-muted-foreground">Nobody has access yet.</li> : null}
      </ul>
      <div className="space-y-3 border-t border-border pt-3">
        <p className="text-xs font-medium">Give someone access</p>
        <Field id="mm-user" label="User" error={errors.userId}>
          <select id="mm-user" className={inputClass} value={userId} onChange={(e) => setUserId(e.target.value)}>
            <option value="">Choose a user…</option>
            {options.users.map((u) => <option key={u.id} value={u.id}>{u.name} ({u.email})</option>)}
          </select>
        </Field>
        <Field id="mm-role" label="Role" error={errors.roleKey}>
          <select id="mm-role" className={inputClass} value={roleKey} onChange={(e) => setRoleKey(e.target.value)}>
            {options.roles.map((r) => <option key={r.key} value={r.key}>{r.name}</option>)}
          </select>
        </Field>
        {role ? <p className="text-xs text-muted-foreground">{role.description}</p> : null}
        {role?.siteScoped ? (
          <Field id="mm-site" label="Website" error={errors.siteId}>
            <select id="mm-site" className={inputClass} value={siteId} onChange={(e) => setSiteId(e.target.value)}>
              <option value="all">All websites in this organization</option>
              {options.sites.map((s) => <option key={s.id} value={s.id}>{s.name}</option>)}
            </select>
          </Field>
        ) : null}
        <Button disabled={pending || !userId || !roleKey} onClick={() => run(() => assignMemberAction(orgId, { userId, roleKey, siteId: role?.siteScoped ? siteId : "all" }), () => setUserId(""))}>Give access</Button>
      </div>
      <Status msg={msg} />
    </Card>
  );
}

export interface DomainRow { id: string; hostname: string; isPrimary: boolean }

/**
 * A website's domains: change a name (e.g. a test domain to the live one), add more, choose the primary and remove extras.
 * The public site is picked by hostname, so changes apply on the next request; DNS and the web server must know the name too.
 */
export function SiteDomains({ siteId, siteName, domains }: { siteId: string; siteName: string; domains: DomainRow[] }) {
  const { pending, msg, errors, run } = useRun();
  const [editing, setEditing] = useState<string | null>(null);
  const [draft, setDraft] = useState("");
  const [adding, setAdding] = useState("");
  const [makePrimary, setMakePrimary] = useState(false);
  const [confirmRemove, setConfirmRemove] = useState<string | null>(null);
  const idp = `dom-${siteId}`;
  return (
    <details className="rounded-md border border-border p-2 text-sm">
      <summary className="cursor-pointer text-xs font-medium">Domains ({domains.length})</summary>
      <ul className="mt-2 divide-y divide-border">
        {domains.map((d) => (
          <li key={d.id} className="flex flex-wrap items-center gap-2 py-2">
            {editing === d.id ? (
              <>
                <label htmlFor={`${idp}-e-${d.id}`} className="sr-only">New domain for {d.hostname}</label>
                <input id={`${idp}-e-${d.id}`} className={`${inputClass} min-w-0 flex-1`} value={draft} onChange={(e) => setDraft(e.target.value)} placeholder="www.example.com" aria-invalid={errors.hostname ? true : undefined} />
                <Button disabled={pending || !draft.trim()} onClick={() => run(() => updateDomainAction(d.id, { hostname: draft }), () => setEditing(null))}>Save</Button>
                <Button variant="ghost" disabled={pending} onClick={() => setEditing(null)}>Cancel</Button>
              </>
            ) : (
              <>
                <span className="min-w-0 flex-1 break-all font-mono text-xs">{d.hostname}{d.isPrimary ? <span className="ml-2 rounded bg-primary/10 px-1.5 py-0.5 font-sans text-[10px] font-semibold uppercase text-primary">primary</span> : null}</span>
                <Button variant="ghost" disabled={pending} aria-label={`Change ${d.hostname}`} onClick={() => { setEditing(d.id); setDraft(d.hostname); setConfirmRemove(null); }}>Change</Button>
                {!d.isPrimary ? <Button variant="ghost" disabled={pending} aria-label={`Make ${d.hostname} the primary domain`} onClick={() => run(() => setPrimaryDomainAction(d.id))}>Make primary</Button> : null}
                {domains.length > 1 ? (confirmRemove === d.id
                  ? <Button variant="danger" disabled={pending} onClick={() => run(() => removeDomainAction(d.id), () => setConfirmRemove(null))}>Confirm remove</Button>
                  : <Button variant="ghost" disabled={pending} aria-label={`Remove ${d.hostname}`} onClick={() => setConfirmRemove(d.id)}>Remove</Button>) : null}
              </>
            )}
          </li>
        ))}
      </ul>
      <div className="mt-2 grid gap-2 sm:grid-cols-[1fr_auto_auto] sm:items-end">
        <Field id={`${idp}-add`} label={`Add a domain to ${siteName}`} error={editing ? undefined : errors.hostname}>
          <input id={`${idp}-add`} className={inputClass} value={adding} onChange={(e) => setAdding(e.target.value)} placeholder="www.example.com" />
        </Field>
        <label className="flex items-center gap-2 pb-2 text-xs"><input type="checkbox" checked={makePrimary} onChange={(e) => setMakePrimary(e.target.checked)} />Make primary</label>
        <Button disabled={pending || !adding.trim()} onClick={() => run(() => addDomainAction(siteId, { hostname: adding, primary: makePrimary }), () => { setAdding(""); setMakePrimary(false); })}>Add</Button>
      </div>
      {editing && errors.hostname ? <p role="alert" className="text-xs text-danger">{errors.hostname}</p> : null}
      <Status msg={msg} />
      <p className="mt-1 text-xs text-muted-foreground">Add both <span className="font-mono">example.com</span> and <span className="font-mono">www.example.com</span> if visitors may use either. Point each name&rsquo;s DNS at this server and add it in the web server (cPanel alias + SSL); the platform does not check ownership.</p>
    </details>
  );
}
