import * as React from "react";
import { useTranslation } from "react-i18next";
import { GitBranch, ListPlus, Minus, Plus, Settings2, Users } from "lucide-react";
import { listAgents } from "@/api/agents";
import { createTeam, createTeamConfig, updateTeam, updateTeamConfig } from "@/api";
import { Button } from "@/components/ui/button";
import { Dialog } from "@/components/ui/dialog";
import { Input, Textarea } from "@/components/ui/input";
import { Select } from "@/components/ui/select";
import { toast } from "@/components/ui/toaster";
import { useAuthStore } from "@/stores/auth";
import type { AgentDefinition, JSONObject, TeamConfig, TeamDefinition } from "@/types";

type MemberDraft = {
  role: string;
  agent_id: string;
  responsibility: string;
};

type PolicyDraft = {
  max_rounds: string;
  handoff: string;
  failure_mode: string;
};

const DEFAULT_POLICY: PolicyDraft = {
  max_rounds: "3",
  handoff: "supervisor",
  failure_mode: "stop_on_critical",
};

function createDefaultMember(): MemberDraft {
  return { role: "executor", agent_id: "", responsibility: "" };
}

export function CreateTeamDialog({
  open,
  onOpenChange,
  onCreated,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onCreated: (team: TeamDefinition) => void;
}) {
  const { t } = useTranslation();
  const { userId } = useAuthStore();
  const [form, setForm] = React.useState({ name: "", description: "", coordination_mode: "supervisor", objective: "" });
  const [members, setMembers] = React.useState<MemberDraft[]>([createDefaultMember()]);
  const [policy, setPolicy] = React.useState<PolicyDraft>(DEFAULT_POLICY);
  const [agents, setAgents] = React.useState<AgentDefinition[]>([]);
  const [formError, setFormError] = React.useState<string>();
  const [submitting, setSubmitting] = React.useState(false);

  React.useEffect(() => {
    if (!open) return;
    void listAgents().then(setAgents).catch(() => {});
  }, [open]);

  function reset() {
    setForm({ name: "", description: "", coordination_mode: "supervisor", objective: "" });
    setMembers([createDefaultMember()]);
    setPolicy(DEFAULT_POLICY);
    setFormError(undefined);
  }

  async function submit(event: React.FormEvent) {
    event.preventDefault();
    if (!form.name.trim()) return;

    const configPayload = buildTeamConfig(members, agents, policy, t);
    if (!configPayload.ok) {
      setFormError(configPayload.message);
      return;
    }

    setSubmitting(true);
    setFormError(undefined);
    try {
      const team = await createTeam({ name: form.name, description: form.description || undefined, team_type: "collaborative", owner_user_id: userId });
      await createTeamConfig({
        team_id: team.id,
        coordination_mode: form.coordination_mode,
        objective: form.objective || undefined,
        member_refs: configPayload.memberRefs,
        policy_json: configPayload.policyJson,
      });
      toast.success(t("teams.teamCreated"));
      onOpenChange(false);
      reset();
      onCreated(team);
    } catch (err) {
      toast.error(err instanceof Error ? err.message : t("teams.failedCreateTeam"));
    } finally {
      setSubmitting(false);
    }
  }

  return (
    <Dialog
      open={open}
      onOpenChange={(value) => { if (!value) reset(); onOpenChange(value); }}
      title={t("teams.newTeam")}
      description={t("teams.createTeamDefineObjective")}
      className="max-w-6xl"
    >
      <form className="space-y-4" onSubmit={submit}>
        <div className="grid gap-3 rounded-md border border-border bg-muted/20 p-3 sm:grid-cols-3">
          <SummaryPill icon={<GitBranch className="h-4 w-4" />} label={t("teams.coordination")} value={t(`teams.${form.coordination_mode}`)} />
          <SummaryPill icon={<Users className="h-4 w-4" />} label={t("teams.members")} value={String(members.length)} />
          <SummaryPill icon={<Settings2 className="h-4 w-4" />} label={t("teams.maxRoundsField")} value={policy.max_rounds} />
        </div>

        <div className="grid gap-4 xl:grid-cols-[0.95fr_1.25fr]">
          <div className="space-y-4">
            <section className="rounded-md border border-border bg-muted/10 p-4">
              <SectionHeader icon={<ListPlus className="h-4 w-4" />} title={t("teams.basicInfo")} />
              <div className="mt-4 space-y-4">
                <div className="grid gap-4 sm:grid-cols-[1fr_190px]">
                  <Field label={t("common.name")}>
                    <Input required value={form.name} onChange={(event) => setForm({ ...form, name: event.target.value })} />
                  </Field>
                  <Field label={t("teams.coordinationMode")}>
                    <Select
                      value={form.coordination_mode}
                      onChange={(event) => setForm({ ...form, coordination_mode: event.target.value })}
                      options={coordinationModeOptions(t)}
                    />
                    <p className="text-xs leading-5 text-muted-foreground">
                      {coordinationModeDescription(t, form.coordination_mode)}
                    </p>
                  </Field>
                </div>
                <Field label={t("common.description")}>
                  <Textarea className="min-h-20" value={form.description} onChange={(event) => setForm({ ...form, description: event.target.value })} />
                </Field>
                <Field label={t("teams.objective")}>
                  <Textarea className="min-h-24" value={form.objective} placeholder={t("teams.describeObjective")} onChange={(event) => setForm({ ...form, objective: event.target.value })} />
                </Field>
              </div>
            </section>

            <PolicyEditor policy={policy} onChange={setPolicy} />
          </div>

          <MemberEditor members={members} onChange={setMembers} agents={agents} />
        </div>

        {formError ? <p className="rounded-md border border-red-500/25 bg-red-500/5 p-3 text-sm text-foreground">{formError}</p> : null}
        <div className="sticky bottom-0 -mx-4 -mb-4 flex justify-end gap-2 border-t border-border bg-surface-elevated/95 px-4 py-4 backdrop-blur sm:-mx-5 sm:-mb-5 sm:px-5">
          <Button type="button" variant="ghost" onClick={() => { reset(); onOpenChange(false); }}>
            {t("common.cancel")}
          </Button>
          <Button disabled={submitting || !form.name.trim()}>{submitting ? t("common.creating") : t("common.create")}</Button>
        </div>
      </form>
    </Dialog>
  );
}

function MemberEditor({ members, onChange, agents }: { members: MemberDraft[]; onChange: (members: MemberDraft[]) => void; agents: AgentDefinition[] }) {
  const { t } = useTranslation();
  function update(index: number, patch: Partial<MemberDraft>) {
    onChange(members.map((m, i) => (i === index ? { ...m, ...patch } : m)));
  }
  function remove(index: number) {
    onChange(members.filter((_, i) => i !== index));
  }

  const agentOptions = React.useMemo(
    () => [
      { value: "", label: t("teams.selectAgent") },
      ...agents.map((a) => ({ value: a.id, label: a.name })),
    ],
    [agents, t],
  );

  return (
    <section className="space-y-4 rounded-md border border-border bg-muted/10 p-4">
      <SectionHeader
        icon={<Users className="h-4 w-4" />}
        title={t("teams.members")}
        action={
          <Button type="button" size="sm" variant="outline" onClick={() => onChange([...members, createDefaultMember()])}>
            <Plus className="h-4 w-4" /> {t("teams.addMember")}
          </Button>
        }
      />
      {members.length ? (
        <div className="max-h-[520px] space-y-3 overflow-auto pr-1">
          {members.map((member, index) => (
            <div key={index} className="rounded-md border border-border bg-surface-elevated px-4 py-3 shadow-sm">
              <div className="mb-3 flex items-center justify-between gap-3">
                <p className="text-sm font-medium">{t("teams.member")} {index + 1}</p>
                <Button
                  type="button"
                  size="icon"
                  variant="ghost"
                  className="h-8 w-8 shrink-0 text-muted-foreground hover:text-red-500"
                  disabled={members.length <= 1}
                  onClick={() => remove(index)}
                  aria-label={t("teams.remove")}
                >
                  <Minus className="h-4 w-4" />
                </Button>
              </div>
              <div className="grid gap-3 lg:grid-cols-[180px_1fr]">
                <Field label={t("teams.role")}>
                  <Select
                    aria-label={`${t("teams.role")} ${index + 1}`}
                    value={member.role}
                    onChange={(event) => update(index, { role: event.target.value })}
                    options={[
                      { value: "supervisor", label: t("teams.supervisor") },
                      { value: "executor", label: t("teams.executor") },
                      { value: "reviewer", label: t("teams.reviewer") },
                      { value: "planner", label: t("teams.planner") },
                    ]}
                  />
                </Field>
                <Field label={t("teams.selectAgent")}>
                  <Select
                    aria-label={`${t("teams.agent")} ${index + 1}`}
                    value={member.agent_id}
                    onChange={(event) => update(index, { agent_id: event.target.value })}
                    options={agentOptions}
                  />
                </Field>
              </div>
              <Field label={t("teams.responsibility")}>
                <Textarea
                  className="min-h-16"
                  aria-label={`${t("teams.responsibility")} ${index + 1}`}
                  value={member.responsibility}
                  placeholder={t("teams.responsibility")}
                  onChange={(event) => update(index, { responsibility: event.target.value })}
                />
              </Field>
            </div>
          ))}
        </div>
      ) : (
        <div className="rounded-md border border-dashed border-border py-8 text-center text-sm text-muted-foreground">
          {t("teams.noMembersHint")}
        </div>
      )}
    </section>
  );
}

function PolicyEditor({ policy, onChange }: { policy: PolicyDraft; onChange: (policy: PolicyDraft) => void }) {
  const { t } = useTranslation();
  return (
    <section className="space-y-4 rounded-md border border-border bg-muted/10 p-4">
      <SectionHeader icon={<Settings2 className="h-4 w-4" />} title={t("teams.policy")} />
      <div className="grid gap-4">
        <Field label={t("teams.maxRoundsField")}>
          <Input type="number" min={1} max={20} value={policy.max_rounds} onChange={(event) => onChange({ ...policy, max_rounds: event.target.value })} />
        </Field>
        <Field label={t("teams.handoff")}>
          <Select
            value={policy.handoff}
            onChange={(event) => onChange({ ...policy, handoff: event.target.value })}
            options={[
              { value: "supervisor", label: t("teams.supervisor") },
              { value: "round_robin", label: t("teams.roundRobin") },
              { value: "parallel_merge", label: t("teams.parallelMerge") },
            ]}
          />
        </Field>
        <Field label={t("teams.failureMode")}>
          <Select
            value={policy.failure_mode}
            onChange={(event) => onChange({ ...policy, failure_mode: event.target.value })}
            options={[
              { value: "stop_on_critical", label: t("teams.stopOnCritical") },
              { value: "continue_with_warning", label: t("teams.continueWithWarning") },
              { value: "retry_once", label: t("teams.retryOnce") },
            ]}
          />
        </Field>
      </div>
    </section>
  );
}

function SectionHeader({ icon, title, action }: { icon: React.ReactNode; title: string; action?: React.ReactNode }) {
  return (
    <div className="flex items-center justify-between gap-3">
      <div className="flex items-center gap-2 rounded-md border border-border bg-muted/30 px-3 py-1.5">
        <div className="grid h-6 w-6 shrink-0 place-items-center rounded bg-primary/15 text-primary">{icon}</div>
        <span className="text-sm font-medium">{title}</span>
      </div>
      {action}
    </div>
  );
}

export function EditTeamDialog({
  open,
  onOpenChange,
  team,
  activeConfig,
  onUpdated,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  team?: TeamDefinition;
  activeConfig?: TeamConfig;
  onUpdated: (team: TeamDefinition) => void;
}) {
  const { t } = useTranslation();
  const [form, setForm] = React.useState({ name: "", description: "", coordination_mode: "supervisor", objective: "" });
  const [members, setMembers] = React.useState<MemberDraft[]>([createDefaultMember()]);
  const [policy, setPolicy] = React.useState<PolicyDraft>(DEFAULT_POLICY);
  const [agents, setAgents] = React.useState<AgentDefinition[]>([]);
  const [formError, setFormError] = React.useState<string>();
  const [submitting, setSubmitting] = React.useState(false);

  React.useEffect(() => {
    if (!open) return;
    void listAgents().then(setAgents).catch(() => {});
  }, [open]);

  React.useEffect(() => {
    if (!open || !team) return;
    setForm({
      name: team.name,
      description: team.description ?? "",
      coordination_mode: activeConfig?.coordination_mode ?? "supervisor",
      objective: activeConfig?.objective ?? "",
    });
    setMembers(readMemberDrafts(activeConfig));
    setPolicy(readPolicyDraft(activeConfig));
    setFormError(undefined);
  }, [activeConfig, open, team]);

  async function submit(event: React.FormEvent) {
    event.preventDefault();
    if (!team || !form.name.trim()) return;

    const configPayload = buildTeamConfig(members, agents, policy, t);
    if (!configPayload.ok) {
      setFormError(configPayload.message);
      return;
    }

    setSubmitting(true);
    setFormError(undefined);
    try {
      const updatedTeam = await updateTeam(team.id, {
        name: form.name,
        description: form.description || null,
        team_type: team.team_type,
        owner_user_id: team.owner_user_id,
      });
      if (activeConfig) {
        await updateTeamConfig(activeConfig.id, {
          coordination_mode: form.coordination_mode,
          objective: form.objective || null,
          member_refs: configPayload.memberRefs,
          policy_json: configPayload.policyJson,
        });
      } else {
        await createTeamConfig({
          team_id: team.id,
          coordination_mode: form.coordination_mode,
          objective: form.objective || undefined,
          member_refs: configPayload.memberRefs,
          policy_json: configPayload.policyJson,
        });
      }
      toast.success(t("teams.teamUpdated"));
      onOpenChange(false);
      onUpdated(updatedTeam);
    } catch (err) {
      toast.error(err instanceof Error ? err.message : t("teams.failedUpdateTeam"));
    } finally {
      setSubmitting(false);
    }
  }

  return (
    <Dialog
      open={open}
      onOpenChange={onOpenChange}
      title={t("teams.editTeam")}
      description={team?.name ?? t("teams.teamDetails")}
      className="max-w-6xl"
    >
      <form className="space-y-4" onSubmit={submit}>
        <div className="grid gap-3 rounded-md border border-border bg-muted/20 p-3 sm:grid-cols-3">
          <SummaryPill icon={<GitBranch className="h-4 w-4" />} label={t("teams.coordination")} value={t(`teams.${form.coordination_mode}`)} />
          <SummaryPill icon={<Users className="h-4 w-4" />} label={t("teams.members")} value={String(members.length)} />
          <SummaryPill icon={<Settings2 className="h-4 w-4" />} label={t("teams.maxRoundsField")} value={policy.max_rounds} />
        </div>

        <div className="grid gap-4 xl:grid-cols-[0.95fr_1.25fr]">
          <div className="space-y-4">
            <section className="rounded-md border border-border bg-muted/10 p-4">
              <SectionHeader icon={<ListPlus className="h-4 w-4" />} title={t("teams.basicInfo")} />
              <div className="mt-4 space-y-4">
                <div className="grid gap-4 sm:grid-cols-[1fr_190px]">
                  <Field label={t("common.name")}>
                    <Input required value={form.name} onChange={(event) => setForm({ ...form, name: event.target.value })} />
                  </Field>
                  <Field label={t("teams.coordinationMode")}>
                    <Select
                      value={form.coordination_mode}
                      onChange={(event) => setForm({ ...form, coordination_mode: event.target.value })}
                      options={coordinationModeOptions(t)}
                    />
                    <p className="text-xs leading-5 text-muted-foreground">
                      {coordinationModeDescription(t, form.coordination_mode)}
                    </p>
                  </Field>
                </div>
                <Field label={t("common.description")}>
                  <Textarea className="min-h-20" value={form.description} onChange={(event) => setForm({ ...form, description: event.target.value })} />
                </Field>
                <Field label={t("teams.objective")}>
                  <Textarea className="min-h-24" value={form.objective} placeholder={t("teams.describeObjective")} onChange={(event) => setForm({ ...form, objective: event.target.value })} />
                </Field>
              </div>
            </section>

            <PolicyEditor policy={policy} onChange={setPolicy} />
          </div>

          <MemberEditor members={members} onChange={setMembers} agents={agents} />
        </div>

        {formError ? <p className="rounded-md border border-red-500/25 bg-red-500/5 p-3 text-sm text-foreground">{formError}</p> : null}
        <div className="sticky bottom-0 -mx-4 -mb-4 flex justify-end gap-2 border-t border-border bg-surface-elevated/95 px-4 py-4 backdrop-blur sm:-mx-5 sm:-mb-5 sm:px-5">
          <Button type="button" variant="ghost" onClick={() => onOpenChange(false)}>
            {t("common.cancel")}
          </Button>
          <Button disabled={submitting || !form.name.trim()}>{submitting ? t("common.saving") : t("common.save")}</Button>
        </div>
      </form>
    </Dialog>
  );
}

function SummaryPill({ icon, label, value }: { icon: React.ReactNode; label: string; value: string }) {
  return (
    <div className="flex items-center gap-3 rounded-md border border-border bg-surface-elevated px-3 py-2">
      <div className="grid h-8 w-8 shrink-0 place-items-center rounded bg-primary/15 text-primary">{icon}</div>
      <div className="min-w-0">
        <p className="text-xs text-muted-foreground">{label}</p>
        <p className="truncate text-sm font-medium">{value}</p>
      </div>
    </div>
  );
}

function coordinationModeOptions(t: (key: string) => string) {
  return [
    { value: "supervisor", label: t("teams.coordinationSupervisorOption") },
    { value: "pipeline", label: t("teams.coordinationPipelineOption") },
    { value: "parallel", label: t("teams.coordinationParallelOption") },
    { value: "debate", label: t("teams.coordinationDebateOption") },
  ];
}

function coordinationModeDescription(t: (key: string) => string, mode: string) {
  const keyByMode: Record<string, string> = {
    supervisor: "coordinationSupervisorDescription",
    pipeline: "coordinationPipelineDescription",
    parallel: "coordinationParallelDescription",
    debate: "coordinationDebateDescription",
  };
  return t(`teams.${keyByMode[mode] ?? keyByMode.supervisor}`);
}

function Field({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <label className="block space-y-1.5 text-sm">
      <span className="text-muted-foreground">{label}</span>
      {children}
    </label>
  );
}

function buildTeamConfig(
  members: MemberDraft[],
  agents: AgentDefinition[],
  policy: PolicyDraft,
  t: (key: string) => string,
):
  | { ok: true; memberRefs: JSONObject[]; policyJson: JSONObject }
  | { ok: false; message: string } {
  const agentNameById = new Map(agents.map((agent) => [agent.id, agent.name]));
  const normalizedMembers = members
    .map((m) => {
      const agentId = m.agent_id.trim();
      const agentName = agentNameById.get(agentId);
      const member: JSONObject = {
        role: m.role.trim(),
        agent_id: agentId,
        responsibility: m.responsibility.trim(),
      };
      if (agentName) {
        member.name = agentName;
        member.agent_name = agentName;
      }
      return member;
    })
    .filter((m) => m.role || m.agent_id || m.responsibility);
  if (!normalizedMembers.length) return { ok: false, message: t("teams.addAtLeastOneMember") };
  if (normalizedMembers.some((m) => !m.agent_id)) return { ok: false, message: t("teams.eachMemberNeedsAgentId") };
  const maxRounds = Number(policy.max_rounds);
  if (!Number.isInteger(maxRounds) || maxRounds < 1 || maxRounds > 20) return { ok: false, message: t("teams.maxRoundsMustBe") };
  return {
    ok: true,
    memberRefs: normalizedMembers,
    policyJson: { max_rounds: maxRounds, handoff: policy.handoff, failure_mode: policy.failure_mode },
  };
}

function readMemberDrafts(activeConfig?: TeamConfig): MemberDraft[] {
  if (!activeConfig?.member_refs_json.length) return [createDefaultMember()];
  return activeConfig.member_refs_json.map((member) => ({
    role: readString(member, "role") ?? "executor",
    agent_id: readString(member, "agent_id") ?? readString(member, "agentId") ?? "",
    responsibility: readString(member, "responsibility") ?? readString(member, "description") ?? "",
  }));
}

function readPolicyDraft(activeConfig?: TeamConfig): PolicyDraft {
  if (!activeConfig) return DEFAULT_POLICY;
  return {
    max_rounds: readString(activeConfig.policy_json, "max_rounds") ?? DEFAULT_POLICY.max_rounds,
    handoff: readString(activeConfig.policy_json, "handoff") ?? DEFAULT_POLICY.handoff,
    failure_mode: readString(activeConfig.policy_json, "failure_mode") ?? DEFAULT_POLICY.failure_mode,
  };
}

function readString(value: JSONObject, key: string) {
  const item = value[key];
  if (typeof item === "string" && item.trim()) return item;
  if (typeof item === "number" || typeof item === "boolean") return String(item);
  return undefined;
}
