import { useEffect, useMemo, useState, type CSSProperties } from "react";
import { toast } from "sonner";
import { useLocation, useNavigate } from "react-router-dom";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
  faCloudArrowUp,
  faEye,
  faEyeSlash,
  faPenToSquare,
  faPlus,
  faRotate,
  faRocket
} from "@fortawesome/free-solid-svg-icons";
import { Card, CardContent } from "../components/ui/card";
import { Button } from "../components/ui/button";
import { Input } from "../components/ui/input";
import { Label } from "../components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../components/ui/select";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../components/ui/tabs";
import {
  createDeployment,
  deleteDeployment,
  DeploymentInput,
  DeploymentProject,
  fetchDeploymentComposeFiles,
  fetchDeploymentBranches,
  fetchDeploymentEnvExamples,
  fetchDeployments,
  restartDeployment,
  runDeployment,
  updateDeployment
} from "../api/deployments";
import { JobStatusBadge } from "../components/JobStatusBadge";
import { useLiveData } from "../providers/live-provider";

type FormState = {
  _id?: string;
  name: string;
  repoUrl: string;
  branch: string;
  composeFile: DeploymentInput["composeFile"];
  port: string;
};

type EnvExample = { name: string; content: string };

const defaultForm: FormState = {
  name: "",
  repoUrl: "",
  branch: "main",
  composeFile: "docker-compose.yml",
  port: ""
};

export function DeploymentsPage() {
  const navigate = useNavigate();
  const location = useLocation();
  const { deploymentStreams } = useLiveData();
  const apiBase = (import.meta.env.VITE_API_URL || "").replace(/\/$/, "");
  const [deployments, setDeployments] = useState<DeploymentProject[]>([]);
  const [loading, setLoading] = useState(false);
  const [modalOpen, setModalOpen] = useState(false);
  const [saving, setSaving] = useState(false);
  const [form, setForm] = useState<FormState>(defaultForm);
  const [pendingEditId, setPendingEditId] = useState<string | null>(null);
  const [branchOptions, setBranchOptions] = useState<string[]>([]);
  const [branchLoading, setBranchLoading] = useState(false);
  const [composeOptions, setComposeOptions] = useState<DeploymentInput["composeFile"][]>([]);
  const [composeLoading, setComposeLoading] = useState(false);
  const [envExamples, setEnvExamples] = useState<EnvExample[]>([]);
  const [envLoading, setEnvLoading] = useState(false);
  const [envContent, setEnvContent] = useState("");
  const [envExampleName, setEnvExampleName] = useState("");
  const [showEnv, setShowEnv] = useState(false);
  const [activeTab, setActiveTab] = useState("details");
  const [faviconErrors, setFaviconErrors] = useState<Record<string, boolean>>({});

  const isEdit = useMemo(() => !!form._id, [form._id]);

  const loadDeployments = async () => {
    setLoading(true);
    try {
      const data = await fetchDeployments();
      setDeployments(data);
    } catch {
      toast.error("Deployment listesi alınamadı");
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    loadDeployments();
  }, []);

  useEffect(() => {
    const repoUrl = form.repoUrl.trim();
    if (!repoUrl) {
      setBranchOptions([]);
      setComposeOptions([]);
      return;
    }
    if (!form._id && !form.name) {
      const normalized = repoUrl.replace(/\/+$/, "");
      const lastPart = normalized.split("/").pop() || "";
      const name = lastPart.replace(/\.git$/i, "");
      if (name) {
        setForm((prev) => ({ ...prev, name }));
      }
    }
    const timer = setTimeout(async () => {
      setBranchLoading(true);
      try {
        const branches = await fetchDeploymentBranches(repoUrl);
        setBranchOptions(branches);
        if (!form.branch && branches.length > 0) {
          setForm((prev) => ({ ...prev, branch: branches.includes("main") ? "main" : branches[0] }));
        }
      } catch {
        setBranchOptions([]);
      } finally {
        setBranchLoading(false);
      }
    }, 400);
    return () => clearTimeout(timer);
  }, [form.repoUrl, form.branch]);

  useEffect(() => {
    const repoUrl = form.repoUrl.trim();
    const branch = form.branch.trim();
    if (!repoUrl || !branch) {
      setEnvExamples([]);
      setEnvExampleName("");
      if (!isEdit) {
        setEnvContent("");
      }
      setComposeOptions([]);
      return;
    }
    const timer = setTimeout(async () => {
      setComposeLoading(true);
      try {
        const files = await fetchDeploymentComposeFiles(repoUrl, branch);
        setComposeOptions(files);
        if (files.length > 0 && !files.includes(form.composeFile)) {
          setForm((prev) => ({ ...prev, composeFile: files[0] }));
        }
      } catch {
        setComposeOptions([]);
      } finally {
        setComposeLoading(false);
      }
    }, 400);
    return () => clearTimeout(timer);
  }, [form.repoUrl, form.branch, form.composeFile]);

  useEffect(() => {
    const repoUrl = form.repoUrl.trim();
    const branch = form.branch.trim();
    if (!repoUrl || !branch) {
      return;
    }
    const timer = setTimeout(async () => {
      setEnvLoading(true);
      try {
        const examples = await fetchDeploymentEnvExamples(repoUrl, branch);
        setEnvExamples(examples);
        if (examples.length === 0) {
          if (!isEdit) {
            setEnvExampleName("");
            setEnvContent("");
          }
          return;
        }
        const selected = examples.find((example) => example.name === envExampleName) || examples[0];
        if (!isEdit || !envContent) {
          setEnvExampleName(selected.name);
          setEnvContent(selected.content);
        }
      } catch {
        setEnvExamples([]);
      } finally {
        setEnvLoading(false);
      }
    }, 400);
    return () => clearTimeout(timer);
  }, [form.repoUrl, form.branch, envExampleName, isEdit]);

  useEffect(() => {
    const state = location.state as { editDeploymentId?: string } | null;
    if (state?.editDeploymentId) {
      setPendingEditId(state.editDeploymentId);
      navigate(location.pathname, { replace: true });
    }
  }, [location.state, navigate, location.pathname]);

  useEffect(() => {
    if (!pendingEditId || deployments.length === 0) return;
    const deployment = deployments.find((d) => d._id === pendingEditId);
    if (deployment) {
      handleEdit(deployment);
      setPendingEditId(null);
    }
  }, [pendingEditId, deployments]);

  const handleOpenNew = async () => {
    setForm(defaultForm);
    setBranchOptions([]);
    setComposeOptions([]);
    setEnvExamples([]);
    setEnvContent("");
    setEnvExampleName("");
    setShowEnv(false);
    setActiveTab("details");
    setModalOpen(true);
  };

  const handleEdit = (deployment: DeploymentProject) => {
    const { _id, name, repoUrl, branch, composeFile, port } = deployment;
    setForm({
      _id,
      name,
      repoUrl,
      branch,
      composeFile,
      port: port ? String(port) : ""
    });
    setEnvContent(deployment.envContent || "");
    setEnvExampleName(deployment.envExampleName || "");
    setShowEnv(false);
    setActiveTab("details");
    setModalOpen(true);
  };

  const handleClose = () => {
    setModalOpen(false);
  };

  const handleSave = async () => {
    setSaving(true);
    try {
      const payload: DeploymentInput = {
        name: form.name,
        repoUrl: form.repoUrl,
        branch: form.branch,
        composeFile: form.composeFile,
        port: form.port ? Number(form.port) : undefined,
        envContent: envContent.trim() ? envContent : undefined,
        envExampleName: envExampleName || undefined
      };

      if (!payload.name || !payload.repoUrl || !payload.branch || !payload.composeFile) {
        toast.error("Tüm alanları doldurun");
        setSaving(false);
        return;
      }

      if (isEdit && form._id) {
        const updated = await updateDeployment(form._id, {
          name: payload.name,
          repoUrl: payload.repoUrl,
          branch: payload.branch,
          composeFile: payload.composeFile,
          port: payload.port,
          envContent: payload.envContent,
          envExampleName: payload.envExampleName
        });
        setDeployments((prev) => prev.map((d) => (d._id === updated._id ? updated : d)));
        try {
          await runDeployment(updated._id, "update deploy");
        } catch {
          toast.error("Deploy tetiklenemedi");
        }
        toast.success("Deployment güncellendi");
      } else {
        const created = await createDeployment(payload);
        setDeployments((prev) => [created, ...prev]);
        toast.success("Deployment oluşturuldu");
      }

      setModalOpen(false);
    } catch {
      toast.error("İşlem sırasında hata oluştu");
    } finally {
      setSaving(false);
    }
  };

  const handleRun = async (id: string) => {
    try {
      await runDeployment(id);
      toast.success("Deploy tetiklendi");
    } catch {
      toast.error("Deploy tetiklenemedi");
    }
  };

  const handleRestart = async (id: string) => {
    try {
      await restartDeployment(id, "restart");
      toast.success("Restart tetiklendi");
    } catch {
      toast.error("Restart tetiklenemedi");
    }
  };

  const handleDelete = async (deployment: DeploymentProject) => {
    const ok = window.confirm("Bu deployment'ı silmek istediğinize emin misiniz?");
    if (!ok) return;
    try {
      await deleteDeployment(deployment._id);
      setDeployments((prev) => prev.filter((d) => d._id !== deployment._id));
      toast.success("Deployment silindi");
    } catch {
      toast.error("Deployment silinemedi");
    }
  };

  const formatDate = (value?: string) => {
    if (!value) return "-";
    return new Date(value).toLocaleString();
  };

  return (
    <>
      <div className="flex items-center justify-between gap-4">
        <div>
          <h2 className="text-xl font-semibold text-foreground">Deployments</h2>
        </div>
        <Button onClick={handleOpenNew} className="gap-2">
          <FontAwesomeIcon icon={faPlus} className="h-4 w-4" />
          New Deployment
        </Button>
      </div>

      <div className="grid gap-4">
        {loading && (
          <div className="rounded-md border border-border bg-muted/30 px-4 py-3 text-sm text-muted-foreground">
            Deployments yükleniyor...
          </div>
        )}

        {!loading && deployments.length === 0 && (
          <div className="rounded-md border border-border bg-muted/30 px-4 py-6 text-sm text-muted-foreground">
            Henüz deployment eklenmemiş.
          </div>
        )}

        {deployments.map((deployment) => {
          const faviconUrl = apiBase
            ? `${apiBase}/deployments/${deployment._id}/favicon`
            : `/api/deployments/${deployment._id}/favicon`;
          return (
            <Card
              key={deployment._id}
              className="cursor-pointer transition hover:border-primary/50"
              onClick={() => navigate(`/deployments/${deployment._id}`)}
            >
              <CardContent className="p-5">
                <div className="flex items-start justify-between gap-4">
                  <div className="space-y-2">
                    <div className="flex items-center gap-3">
                      <div className="flex h-9 w-9 items-center justify-center rounded-full bg-primary/10 text-primary">
                        {!faviconErrors[deployment._id] ? (
                          <img
                            src={faviconUrl}
                            alt={`${deployment.name} favicon`}
                            className="h-4 w-4"
                            onError={() =>
                              setFaviconErrors((prev) => ({ ...prev, [deployment._id]: true }))
                            }
                          />
                        ) : (
                          <FontAwesomeIcon icon={faRocket} className="h-4 w-4" />
                        )}
                      </div>
                      <div>
                        <div className="text-base font-semibold text-foreground">{deployment.name}</div>
                        <div className="text-sm text-muted-foreground">{deployment.rootPath}</div>
                      </div>
                    </div>
                    <div className="flex flex-wrap items-center gap-3 text-sm text-muted-foreground">
                      <JobStatusBadge
                        status={deploymentStreams[deployment._id]?.status || deployment.lastStatus}
                      />
                      <span className="rounded-md bg-muted px-2 py-1 text-xs font-semibold text-foreground/80">
                        {deployment.env.toUpperCase()}
                      </span>
                      <span className="rounded-md bg-muted px-2 py-1 text-xs font-semibold text-foreground/80">
                        {deployment.composeFile}
                      </span>
                    </div>
                  </div>

                  <div className="flex items-center gap-2">
                    <Button
                      variant="outline"
                      size="icon"
                      onClick={(e) => {
                        e.stopPropagation();
                        handleRun(deployment._id);
                      }}
                      title="Deploy tetikle"
                    >
                      <FontAwesomeIcon icon={faCloudArrowUp} className="h-4 w-4" />
                    </Button>
                    <Button
                      variant="outline"
                      size="icon"
                      onClick={(e) => {
                        e.stopPropagation();
                        handleRestart(deployment._id);
                      }}
                      title="Restart"
                      aria-label="Restart"
                    >
                      <FontAwesomeIcon icon={faRotate} className="h-4 w-4" />
                    </Button>
                    <Button
                      variant="outline"
                      size="icon"
                      onClick={(e) => {
                        e.stopPropagation();
                        handleEdit(deployment);
                      }}
                      title="Düzenle"
                    >
                      <FontAwesomeIcon icon={faPenToSquare} className="h-4 w-4" />
                    </Button>
                    <Button
                      variant="outline"
                      size="icon"
                      onClick={(e) => {
                        e.stopPropagation();
                        handleDelete(deployment);
                      }}
                      title="Sil"
                    >
                      ✕
                    </Button>
                  </div>
                </div>

                <div className="mt-4 grid gap-1 text-sm text-muted-foreground">
                  <div className="flex items-center gap-2">
                    <span className="font-medium text-foreground">Repo:</span>
                    <span className="truncate text-foreground/80">{deployment.repoUrl}</span>
                  </div>
                  <div className="flex items-center gap-2">
                    <span className="font-medium text-foreground">Branch:</span>
                    <span className="text-foreground/80">{deployment.branch}</span>
                  </div>
                  <div className="flex items-center gap-2">
                    <span className="font-medium text-foreground">Last Deploy:</span>
                    <span className="text-foreground/80">{formatDate(deployment.lastDeployAt)}</span>
                  </div>
                </div>
              </CardContent>
            </Card>
          );
        })}
      </div>

      {modalOpen && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 px-4 py-8">
          <div
            className="flex w-full max-w-lg flex-col overflow-hidden rounded-lg border border-border bg-card card-shadow"
            style={{ height: 626 }}
          >
            <div className="flex items-center justify-between border-b border-border px-5 py-4">
              <div className="space-y-1">
                <div className="text-lg font-semibold text-foreground">
                  {isEdit ? "Deployment Güncelle" : "Yeni Deployment"}
                </div>
                <div className="text-sm text-muted-foreground">
                  Repo ve branch seçimi sonrası webhook tetiklemeleriyle deploy yapılır.
                </div>
              </div>
              <Button variant="ghost" size="icon" onClick={handleClose}>
                ✕
              </Button>
            </div>

            <div className="flex-1 overflow-hidden px-5 py-4">
              <Tabs value={activeTab} onValueChange={setActiveTab} className="space-y-4">
                <TabsList>
                  <TabsTrigger value="details">Genel</TabsTrigger>
                  <TabsTrigger value="environment">Environment</TabsTrigger>
                </TabsList>

                <TabsContent value="details" className="h-[420px] space-y-4">
                  {!isEdit && (
                    <div className="h-[1.25rem] text-xs text-muted-foreground">
                      Repo URL girildiğinde branch ve compose dosyaları listelenir.
                    </div>
                  )}

                  <div className="space-y-2">
                    <Label htmlFor="repo">Repo URL</Label>
                    <Input
                      id="repo"
                      value={form.repoUrl}
                      onChange={(e) => setForm((prev) => ({ ...prev, repoUrl: e.target.value }))}
                      placeholder="https://gitea.example.com/org/repo"
                      required
                    />
                  </div>

                  <div className="grid gap-4 md:grid-cols-2">
                    <div className="space-y-2">
                      <Label htmlFor="name">Deployment Name</Label>
                      <Input
                        id="name"
                        value={form.name}
                        onChange={(e) => setForm((prev) => ({ ...prev, name: e.target.value }))}
                        placeholder="wisecolt-app"
                        required
                      />
                    </div>
                    <div className="space-y-2">
                      <Label htmlFor="branch">Branch</Label>
                      {branchOptions.length > 0 ? (
                        <Select
                          value={form.branch}
                          onValueChange={(value) => setForm((prev) => ({ ...prev, branch: value }))}
                        >
                          <SelectTrigger>
                            <SelectValue placeholder="Branch seçin" />
                          </SelectTrigger>
                          <SelectContent>
                            {branchOptions.map((branch) => (
                              <SelectItem key={branch} value={branch}>
                                {branch}
                              </SelectItem>
                            ))}
                          </SelectContent>
                        </Select>
                      ) : (
                        <Input
                          id="branch"
                          value={form.branch}
                          onChange={(e) => setForm((prev) => ({ ...prev, branch: e.target.value }))}
                          placeholder="main"
                          required
                        />
                      )}
                      <div className="h-[1.25rem] text-xs text-muted-foreground">
                        {branchLoading
                          ? "Branch listesi alınıyor..."
                          : branchOptions.length > 0
                            ? "Repo üzerindeki branch'lar listelendi."
                            : "Repo URL girildiğinde branch listesi otomatik gelir."}
                      </div>
                    </div>
                  </div>

                  <div className="grid gap-4 md:grid-cols-2">
                    <div className="space-y-2">
                      <Label>Compose Dosyası</Label>
                      <Select
                        value={form.composeFile}
                        onValueChange={(value) =>
                          setForm((prev) => ({
                            ...prev,
                            composeFile: value as DeploymentInput["composeFile"]
                          }))
                        }
                      >
                        <SelectTrigger>
                          <SelectValue placeholder="Compose seçin" />
                        </SelectTrigger>
                        <SelectContent>
                          {(composeOptions.length > 0
                            ? composeOptions
                            : ["docker-compose.yml", "docker-compose.dev.yml"]
                          ).map((file) => (
                            <SelectItem key={file} value={file}>
                              {file}
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                      <div className="h-[1.25rem] text-xs text-muted-foreground">
                        {composeLoading
                          ? "Compose dosyaları alınıyor..."
                          : composeOptions.length > 0
                            ? "Repo üzerindeki compose dosyaları listelendi."
                            : "Repo URL ve branch sonrası compose dosyaları listelenir."}
                      </div>
                    </div>

                    <div className="space-y-2">
                      <Label htmlFor="port">Port (opsiyonel)</Label>
                      <Input
                        id="port"
                        type="number"
                        min={1}
                        value={form.port}
                        onChange={(e) => setForm((prev) => ({ ...prev, port: e.target.value }))}
                        placeholder="3000"
                      />
                    </div>
                  </div>
                </TabsContent>

                <TabsContent value="environment" className="h-[420px] space-y-4">
                  <div className="space-y-2">
                    <Label>.env.example</Label>
                    {envExamples.length > 0 ? (
                      <Select
                        value={envExampleName}
                        onValueChange={(value) => {
                          const example = envExamples.find((item) => item.name === value);
                          setEnvExampleName(value);
                          if (example) {
                            setEnvContent(example.content);
                          }
                        }}
                      >
                        <SelectTrigger>
                          <SelectValue placeholder="Env example seçin" />
                        </SelectTrigger>
                        <SelectContent>
                          {envExamples.map((example) => (
                            <SelectItem key={example.name} value={example.name}>
                              {example.name}
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                    ) : (
                      <div className="h-[2.5rem] rounded-md border border-dashed border-border px-3 py-2 text-xs text-muted-foreground">
                        {envLoading
                          ? "Env example dosyaları alınıyor..."
                          : "Repo içinde .env.example bulunamadı."}
                      </div>
                    )}
                    <div className="h-[1.25rem] text-xs text-muted-foreground">
                      {envExamples.length > 0
                        ? "Repo üzerindeki env example dosyaları listelendi."
                        : envLoading
                          ? "Env example dosyaları alınıyor..."
                          : "Repo içinde .env.example bulunamadı."}
                    </div>
                  </div>

                  <div className="space-y-2">
                    <div className="flex items-center justify-between">
                      <Label htmlFor="env-content">Environment</Label>
                      <Button
                        type="button"
                        variant="ghost"
                        size="icon"
                        onClick={() => setShowEnv((prev) => !prev)}
                      >
                        <FontAwesomeIcon icon={showEnv ? faEyeSlash : faEye} className="h-4 w-4" />
                      </Button>
                    </div>
                    <textarea
                      id="env-content"
                      value={envContent}
                      onChange={(e) => setEnvContent(e.target.value)}
                      className="h-[180px] w-full resize-none rounded-md border border-input bg-background px-3 py-2 text-sm font-mono text-foreground shadow-sm outline-none focus-visible:ring-2 focus-visible:ring-ring"
                      style={
                        showEnv ? undefined : ({ WebkitTextSecurity: "disc" } as CSSProperties)
                      }
                      placeholder="ENV içerikleri burada listelenir."
                    />
                    <div className="min-h-[1.25rem] text-xs text-muted-foreground">
                      Kaydedince içerik deployment kök dizinine <span className="font-mono">.env</span> olarak yazılır.
                    </div>
                  </div>
                </TabsContent>
              </Tabs>
            </div>

            <div className="flex items-center justify-end gap-3 border-t border-border px-5 py-4">
              <Button variant="ghost" onClick={handleClose} disabled={saving}>
                İptal
              </Button>
              <Button onClick={handleSave} disabled={saving}>
                {saving ? "Kaydediliyor..." : "Kaydet"}
              </Button>
            </div>
          </div>
        </div>
      )}
    </>
  );
}
