import type { ExecutionEvent, ExecutionStep } from "@/lib/sync/execution/types";
import type { FileSyncExecuteData } from "@/lib/sync/file-sync/types";
import { Button } from "@/components/ui/Button";

const BUMP_STEPS = [
  "precheck",
  "sync-main",
  "create-branch",
  "apply-changes",
  "commit",
  "push",
  "create-pr",
] as const satisfies ExecutionStep[];

const STEP_LABELS: Record<ExecutionStep, string> = {
  "precheck": "Precheck",
  "sync-main": "Sync Main",
  "create-branch": "Create Branch",
  "apply-changes": "Apply Changes",
  "commit": "Commit",
  "push": "Push",
  "create-pr": "Create PR",
  "config-preview": "Config Preview",
  "config-apply": "Config Apply",
  "config-complete": "Config Complete",
};

const PARENTHESIZED_URL_PATTERN = /^(.*)\((https?:\/\/[^)\s]+)\)$/;

function LinkedMessage({ message, url }: { message: string; url?: string }) {
  const safeMessage = typeof message === "string" ? message : "";
  const match = safeMessage.match(PARENTHESIZED_URL_PATTERN);
  if (match) {
    const [, text, href] = match;
    return (
      <span>
        {text.trimEnd()} (
        <a
          href={href}
          target="_blank"
          rel="noopener noreferrer"
          className="text-[#58A6FF] underline hover:text-[#79B8FF] transition-colors"
        >
          {href}
        </a>
        )
      </span>
    );
  }

  if (url) {
    const urlIndex = safeMessage.indexOf(url);
    if (urlIndex >= 0) {
      return (
        <span>
          {safeMessage.slice(0, urlIndex)}
          <a
            href={url}
            target="_blank"
            rel="noopener noreferrer"
            className="text-[#58A6FF] underline hover:text-[#79B8FF] transition-colors"
          >
            {url}
          </a>
          {safeMessage.slice(urlIndex + url.length)}
        </span>
      );
    }
  }

  if (url) {
    return (
      <a
        href={url}
        target="_blank"
        rel="noopener noreferrer"
        className="text-[#58A6FF] underline hover:text-[#79B8FF] transition-colors"
      >
        {safeMessage || url}
      </a>
    );
  }

  return <span>{safeMessage}</span>;
}

function ProgressBar({
  progress,
  bumping,
}: {
  progress: ExecutionEvent[];
  bumping: boolean;
}) {
  const stepStatus = new Map<ExecutionStep, ExecutionEvent["status"]>();
  for (const event of progress) {
    if (event.status === "skipped" && stepStatus.get(event.step) === "success") {
      continue;
    }
    stepStatus.set(event.step, event.status);
  }

  const completedSteps = new Set(
    Array.from(stepStatus.entries())
      .filter(([, status]) => status === "success")
      .map(([step]) => step)
  );

  const total = BUMP_STEPS.length;
  const done = completedSteps.size;
  const pct = Math.round((Math.max(done, 0) / total) * 100);

  return (
    <div className="bg-surface-0 rounded-lg border border-surface-2 p-4">
      <div className="flex items-center justify-between mb-3">
        <span className="text-sm font-medium text-text-secondary">
          Execution Progress
        </span>
        <span className="text-sm font-mono text-text-muted">
          {Math.max(done, 0)}/{total} steps
        </span>
      </div>

      <div className="flex items-center gap-1 mb-3">
        {BUMP_STEPS.map((s, i) => {
          const status = stepStatus.get(s);
          const isDone = completedSteps.has(s);
          const isRunning = status === "running";
          const isFailed = status === "failed";

          return (
            <div key={s} className="flex items-center flex-1 min-w-0">
              <div className="flex items-center gap-2 shrink-0">
                <div
                  className={`w-6 h-6 rounded-full flex items-center justify-center text-xs font-bold transition-all duration-300 ${
                    isDone
                      ? "bg-accent text-white"
                      : isFailed
                        ? "bg-danger text-white"
                        : isRunning
                          ? "bg-warning text-white"
                          : "bg-surface-2 text-text-muted"
                  }`}
                >
                  {i + 1}
                </div>
                <span
                  className={`text-xs whitespace-nowrap transition-colors ${
                    isDone
                      ? "text-accent font-medium"
                      : isFailed
                        ? "text-danger font-medium"
                        : isRunning
                          ? "text-warning font-medium"
                          : "text-text-muted"
                  }`}
                >
                  {STEP_LABELS[s]}
                </span>
              </div>
              {i < BUMP_STEPS.length - 1 && (
                <div
                  className={`flex-1 h-px mx-2 min-w-4 transition-colors ${
                    isDone ? "bg-accent" : "bg-surface-2"
                  }`}
                />
              )}
            </div>
          );
        })}
      </div>

      <div className="h-1.5 bg-surface-1 rounded-full overflow-hidden">
        <div
          className={`h-full rounded-full transition-all duration-500 ease-out ${
            bumping
              ? "progress-shimmer"
              : "bg-gradient-to-r from-accent to-accent-hover"
          }`}
          style={{ width: `${pct}%` }}
        />
      </div>
    </div>
  );
}

export default function ExecutionConsole({
  progress,
  bumping,
  onNewBump,
  configSyncResult,
}: {
  progress: ExecutionEvent[];
  bumping: boolean;
  onNewBump: () => void;
  configSyncResult?: FileSyncExecuteData | null;
}) {
  const groupedConfigErrors = new Map<string, string[]>();
  if (configSyncResult) {
    for (const item of configSyncResult.results) {
      if (!item.error?.code) continue;
      const list = groupedConfigErrors.get(item.error.code) || [];
      list.push(item.regionId);
      groupedConfigErrors.set(item.error.code, list);
    }
  }

  const title = "File Sync Result";

  return (
    <div className="space-y-4">
      <ProgressBar progress={progress} bumping={bumping} />

      {configSyncResult && (
        <div className="bg-surface-0 rounded-lg border border-surface-2 p-4 space-y-3">
          <h3 className="text-sm font-semibold uppercase tracking-wider text-text-secondary">
            {title}
          </h3>

          <div className="flex flex-wrap gap-2 text-xs">
            <span className="px-2 py-1 rounded-md bg-surface-1 text-success">
              Success: {configSyncResult.successCount}
            </span>
            <span className="px-2 py-1 rounded-md bg-surface-1 text-danger">
              Failed: {configSyncResult.failedCount}
            </span>
            <span className="px-2 py-1 rounded-md bg-surface-1 text-warning">
              Skipped: {configSyncResult.skippedCount}
            </span>
          </div>

          {groupedConfigErrors.size > 0 && (
            <div className="space-y-2">
              {Array.from(groupedConfigErrors.entries()).map(([code, regionIds]) => (
                <div key={code} className="text-xs">
                  <div className="font-mono text-danger">{code}</div>
                  <div className="text-text-muted break-all">{regionIds.join(", ")}</div>
                </div>
              ))}
            </div>
          )}
        </div>
      )}

      <div className="bg-[#0D1117] rounded-lg border border-white/10 overflow-hidden">
        <div className="flex items-center gap-2 px-4 py-2.5 border-b border-white/10 bg-white/5">
          <div className="flex gap-1.5">
            <div className="w-3 h-3 rounded-full bg-[#FF5F57]" />
            <div className="w-3 h-3 rounded-full bg-[#FEBC2E]" />
            <div className="w-3 h-3 rounded-full bg-[#28C840]" />
          </div>
          <span className="text-xs text-white/40 ml-2 font-mono">bump — terminal</span>
        </div>

        <div className="p-4 font-mono text-[13px] leading-relaxed min-h-48 space-y-3">
          {progress.map((p, i) => (
            <div key={i} className="space-y-1">
              <div
                className={`flex gap-2 items-start ${
                  p.status === "failed"
                    ? "text-[#FF6B6B]"
                    : p.status === "success"
                      ? "text-[#28C840]"
                      : "text-[#C9D1D9]"
                }`}
              >
                <span className="text-white/25 select-none shrink-0 w-5 text-right">
                  {String(i + 1).padStart(2, "0")}
                </span>
                <div className="flex-1 min-w-0">
                  <div className="flex items-center gap-2">
                    {p.status === "failed" ? (
                      <span className="text-[#FF6B6B]">&#x2717;</span>
                    ) : p.status === "success" ? (
                      <span className="text-[#28C840]">&#x2713;</span>
                    ) : (
                      <span className="text-[#58A6FF]">&#x25B8;</span>
                    )}
                    <LinkedMessage message={p.message} url={p.prUrl} />
                  </div>
                  {p.status === "failed" && p.errorCode && (
                    <div className="mt-1.5 text-[12px] text-[#FFB4B4]">
                      [{p.errorCode}] {p.recoveryHint || "Please check logs and retry."}
                    </div>
                  )}
                  {p.command && (
                    <div className="mt-1.5 pl-4 border-l-2 border-white/10 text-[12px] whitespace-pre-wrap select-all text-[#8B949E]">
                      {p.command.split("\n").map((line: string, li: number) => (
                        <div key={li}>
                          <span className="text-white/30">$ </span>
                          <span className="text-[#C9D1D9]">{line.replace(/^# /, "")}</span>
                        </div>
                      ))}
                    </div>
                  )}
                </div>
              </div>
            </div>
          ))}
          {bumping && (
            <div className="text-white/30 animate-pulse flex gap-2 items-center">
              <span className="w-5 text-right select-none">
                {String(progress.length + 1).padStart(2, "0")}
              </span>
              <span>&#x25B8;</span>
              <span>Waiting...</span>
            </div>
          )}
        </div>
      </div>

      {!bumping && progress.length > 0 && (
        <Button
          onClick={onNewBump}
          variant="secondary"
        >
          New Bump
        </Button>
      )}
    </div>
  );
}
