import { useMemo, useState } from "react";
import type { Region } from "@/lib/types";
import type { SyncableFileName } from "@/lib/sync/file-sync/types";
import type { PerFileSourceStatus } from "@/app/bump/model/file-sync";

function fileStatusBadge(status: PerFileSourceStatus) {
  if (status.hasDiff) return "text-success";
  if (status.unsupportedReasonCode) return "text-warning";
  return "text-text-muted";
}

function fileStatusText(status: PerFileSourceStatus): string {
  if (status.hasDiff) return "Has supported diff";
  if (status.unsupportedReasonCode === "SOURCE_NO_DIFF") return "No diff";
  if (status.unsupportedReasonCode === "SOURCE_FILE_MISSING") return "File missing";
  if (status.unsupportedReasonCode === "UNSUPPORTED_DIFF_PATTERN") return "Unsupported diff";
  return "No diff";
}

export default function FileSyncPanel({
  regions,
  sourceRegionId,
  onSourceRegionChange,
  fileStatuses,
  selectedFiles,
  onSelectedFilesChange,
}: {
  regions: Region[];
  sourceRegionId: string;
  onSourceRegionChange: (regionId: string) => void;
  fileStatuses: PerFileSourceStatus[];
  selectedFiles: Set<SyncableFileName>;
  onSelectedFilesChange: (files: Set<SyncableFileName>) => void;
}) {
  const [sourceSearch, setSourceSearch] = useState("");

  const normalizedSearch = sourceSearch.trim().toLowerCase();
  const filteredRegions = useMemo(() => {
    if (!normalizedSearch) return regions;
    return regions.filter((r) => {
      const tokens = [
        r.architecture,
        r.environment,
        r.provider,
        r.regionName,
        r.id,
        r.directoryPath,
      ];
      return tokens.some((token) => token.toLowerCase().includes(normalizedSearch));
    });
  }, [regions, normalizedSearch]);

  return (
    <div className="p-4 space-y-3 border-b border-surface-2">
      <p className="text-sm text-text-secondary">
        Only changed paths are synced; full files are not overwritten.
      </p>

      <div>
        <label htmlFor="sourceSearch" className="block text-sm font-medium mb-1.5">
          Source Search
        </label>
        <input
          id="sourceSearch"
          aria-label="Source Search"
          value={sourceSearch}
          onChange={(e) => setSourceSearch(e.target.value)}
          placeholder="Search by architecture/env/provider/region/id"
          className="w-full px-3 py-2.5 bg-surface-1 border border-surface-2 rounded-lg text-sm focus:border-accent focus:ring-1 focus:ring-accent/30 transition-colors outline-none mb-3"
        />

        <label className="block text-sm font-medium mb-1.5">
          Source Region
        </label>
        <div
          role="listbox"
          aria-label="Source Region"
          className="max-h-56 overflow-auto rounded-lg border border-surface-2 bg-surface-1"
        >
          {filteredRegions.length === 0 ? (
            <div className="px-3 py-2 text-sm text-text-muted">No matched source regions.</div>
          ) : (
            filteredRegions.map((r) => {
              const selected = r.id === sourceRegionId;
              return (
                <button
                  key={r.id}
                  type="button"
                  role="option"
                  aria-selected={selected}
                  onClick={() => onSourceRegionChange(r.id)}
                  className={`w-full text-left px-3 py-2.5 text-sm border-b last:border-b-0 border-surface-2 transition-colors ${
                    selected
                      ? "bg-accent/10 text-accent"
                      : "text-text-secondary hover:bg-surface-0"
                  }`}
                >
                  <div className="font-medium">
                    {r.architecture}/{r.environment}/{r.provider}/{r.regionName}
                  </div>
                  <div className="text-xs text-text-muted mt-0.5 font-mono">{r.id}</div>
                </button>
              );
            })
          )}
        </div>
      </div>

      {sourceRegionId && fileStatuses.length > 0 && (
        <div>
          <label className="block text-sm font-medium mb-1.5">Files to Sync</label>
          <div className="space-y-1.5">
            {fileStatuses.map((fs) => {
              const checked = selectedFiles.has(fs.sourceFile);
              const disabled = !fs.hasDiff;
              return (
                <label
                  key={fs.sourceFile}
                  className={`flex items-center gap-2 px-3 py-2 rounded-lg border border-surface-2 bg-surface-1 text-sm ${
                    disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer hover:bg-surface-0"
                  }`}
                >
                  <input
                    type="checkbox"
                    checked={checked}
                    disabled={disabled}
                    onChange={(e) => {
                      const next = new Set(selectedFiles);
                      if (e.target.checked) next.add(fs.sourceFile);
                      else next.delete(fs.sourceFile);
                      onSelectedFilesChange(next);
                    }}
                    className="accent-accent"
                  />
                  <span className="font-mono text-xs">{fs.sourceFile}</span>
                  <span className={`text-xs ml-auto ${fileStatusBadge(fs)}`}>
                    {fileStatusText(fs)}
                  </span>
                </label>
              );
            })}
          </div>
        </div>
      )}
    </div>
  );
}
