import {
  AlertCircle,
  ArrowRight,
  CheckCircle2,
  Database,
  FileText,
  Loader2,
  Play,
  Plus,
  Settings2,
  X,
} from "lucide-react";
import {
  type ColumnMetadata,
  type PipelineCondition,
  type PipelineResult,
  type TableMetadata,
} from "@/app/lib/api";
import { Button } from "../ui/button";
import { Input } from "../ui/input";
import { Badge } from "../ui/badge";
import { ScrollArea } from "../ui/scroll-area";
import { AGG_STRATEGY_OPTIONS, TIME_GRANULARITY_OPTIONS } from "./constants";

type BuilderTabProps = {
  clientName: string | null;
  tables: TableMetadata[];
  pipelineName: string;
  setPipelineName: (value: string) => void;
  sourceTable: string;
  setSourceTable: (value: string) => void;
  sourceColumns: string;
  setSourceColumns: (value: string) => void;
  sourceLimit: string;
  setSourceLimit: (value: string) => void;
  sourceTableColumns: ColumnMetadata[];
  columnsLoading: boolean;
  conditions: PipelineCondition[];
  setConditions: (
    updater:
      | PipelineCondition[]
      | ((prev: PipelineCondition[]) => PipelineCondition[]),
  ) => void;
  condCol: string;
  setCondCol: (value: string) => void;
  condVal: string;
  setCondVal: (value: string) => void;
  onAddCondition: () => void;
  groupBy: string;
  setGroupBy: (value: string) => void;
  timeGranularity: string;
  setTimeGranularity: (value: string) => void;
  aggColumn: string;
  setAggColumn: (value: string) => void;
  aggStrategy: string;
  setAggStrategy: (value: string) => void;
  sinkTable: string;
  setSinkTable: (value: string) => void;
  running: boolean;
  onRun: () => void;
  onViewJson: () => void;
  lastResult: PipelineResult | null;
  lastError: string | null;
};

const selectClass =
  "h-8 w-full rounded-md border border-border bg-background px-3 text-xs text-foreground outline-none focus:ring-1 focus:ring-ring transition-colors";

export function BuilderTab(props: BuilderTabProps) {
  const {
    clientName,
    tables,
    pipelineName,
    setPipelineName,
    sourceTable,
    setSourceTable,
    sourceColumns,
    setSourceColumns,
    sourceLimit,
    setSourceLimit,
    sourceTableColumns,
    columnsLoading,
    conditions,
    setConditions,
    condCol,
    setCondCol,
    condVal,
    setCondVal,
    onAddCondition,
    groupBy,
    setGroupBy,
    timeGranularity,
    setTimeGranularity,
    aggColumn,
    setAggColumn,
    aggStrategy,
    setAggStrategy,
    sinkTable,
    setSinkTable,
    running,
    onRun,
    onViewJson,
    lastResult,
    lastError,
  } = props;

  return (
    <div className="flex-1 m-0 overflow-hidden">
      <ScrollArea className="h-full">
        <div className="mx-auto max-w-2xl p-6 space-y-5">
          <section className="rounded-lg border border-border bg-card p-4 space-y-3">
            <h3 className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
              Named Pipeline (optional)
            </h3>
            <Input
              value={pipelineName}
              onChange={(e) => setPipelineName(e.target.value)}
              placeholder="e.g. example_copy (from pipelines.yaml)"
              className="h-8 text-xs"
            />
            <p className="text-caption text-muted-foreground">
              If set, the server resolves source/transform/sink from
              <code className="bg-muted px-1 py-0.5 rounded text-tiny ml-1">
                config/pipelines.yaml
              </code>
              .
            </p>
          </section>

          <section className="rounded-lg border border-border bg-card p-4 space-y-3">
            <h3 className="text-xs font-medium uppercase tracking-wider text-muted-foreground flex items-center gap-2">
              <Database className="h-3.5 w-3.5" /> Source
            </h3>
            <div className="grid grid-cols-2 gap-3">
              <div className="space-y-1">
                <label className="text-caption text-muted-foreground">
                  Table
                </label>
                <select
                  value={sourceTable}
                  onChange={(e) => setSourceTable(e.target.value)}
                  className={selectClass}
                >
                  <option value="">Select table...</option>
                  {tables.map((t) => {
                    const key = `${t.table_schema ?? "public"}.${t.table_name}`;
                    const label = t.table_schema
                      ? `${t.table_schema}.${t.table_name}`
                      : t.table_name;
                    return (
                      <option key={key} value={t.table_name}>
                        {label}
                      </option>
                    );
                  })}
                </select>
              </div>
              <div className="space-y-1">
                <label className="text-caption text-muted-foreground">
                  Limit
                </label>
                <Input
                  type="number"
                  value={sourceLimit}
                  onChange={(e) => setSourceLimit(e.target.value)}
                  placeholder="100"
                  className="h-8 text-xs"
                />
              </div>
            </div>

            <div className="space-y-1">
              <label className="text-caption text-muted-foreground flex items-center gap-1">
                Columns
                {columnsLoading && (
                  <Loader2 className="h-2.5 w-2.5 animate-spin" />
                )}
              </label>
              {sourceTableColumns.length > 0 ? (
                <div className="space-y-1.5">
                  <div className="flex flex-wrap gap-1">
                    {sourceTableColumns.map((col) => {
                      const selected = sourceColumns
                        .split(",")
                        .map((s) => s.trim())
                        .filter(Boolean)
                        .includes(col.column_name);
                      return (
                        <button
                          key={col.column_name}
                          onClick={() => {
                            const current = sourceColumns
                              .split(",")
                              .map((s) => s.trim())
                              .filter(Boolean);
                            if (selected) {
                              setSourceColumns(
                                current
                                  .filter((c) => c !== col.column_name)
                                  .join(", "),
                              );
                            } else {
                              setSourceColumns(
                                [...current, col.column_name].join(", "),
                              );
                            }
                          }}
                          className={`px-2 py-0.5 rounded-md border text-caption transition-colors ${
                            selected
                              ? "border-primary-border bg-primary-muted text-primary"
                              : "border-border bg-background text-muted-foreground hover:border-primary-border hover:text-foreground"
                          }`}
                        >
                          {col.column_name}
                        </button>
                      );
                    })}
                  </div>
                  <p className="text-tiny text-muted-foreground-subtle">
                    Click to toggle columns. Empty = all columns.
                  </p>
                </div>
              ) : (
                <Input
                  value={sourceColumns}
                  onChange={(e) => setSourceColumns(e.target.value)}
                  placeholder="id, email, created_at (blank = all)"
                  className="h-8 text-xs"
                />
              )}
            </div>

            <div className="space-y-2">
              <label className="text-caption text-muted-foreground">
                Conditions
              </label>
              {conditions.map((c, i) => (
                <div key={i} className="flex items-center gap-2 text-body-sm">
                  <Badge variant="secondary" className="text-caption">
                    {c.eq_column} = {c.eq_value}
                  </Badge>
                  <button
                    onClick={() =>
                      setConditions((p) => p.filter((_, j) => j !== i))
                    }
                    className="text-muted-foreground hover:text-destructive"
                  >
                    <X className="h-3 w-3" />
                  </button>
                </div>
              ))}
              <div className="flex gap-2">
                {sourceTableColumns.length > 0 ? (
                  <select
                    value={condCol}
                    onChange={(e) => setCondCol(e.target.value)}
                    className="h-7 flex-1 rounded-md border border-border bg-background px-2 text-body-sm text-foreground outline-none"
                  >
                    <option value="">Select column...</option>
                    {sourceTableColumns.map((col) => (
                      <option key={col.column_name} value={col.column_name}>
                        {col.column_name}
                      </option>
                    ))}
                  </select>
                ) : (
                  <Input
                    value={condCol}
                    onChange={(e) => setCondCol(e.target.value)}
                    placeholder="column"
                    className="h-7 text-body-sm flex-1"
                  />
                )}
                <Input
                  value={condVal}
                  onChange={(e) => setCondVal(e.target.value)}
                  placeholder="value"
                  className="h-7 text-body-sm flex-1"
                />
                <Button
                  variant="outline"
                  size="sm"
                  onClick={onAddCondition}
                  className="h-7 text-caption"
                  disabled={!condCol.trim() || !condVal.trim()}
                >
                  <Plus className="h-3 w-3" />
                </Button>
              </div>
            </div>
          </section>

          <section className="rounded-lg border border-border bg-card p-4 space-y-3">
            <h3 className="text-xs font-medium uppercase tracking-wider text-muted-foreground flex items-center gap-2">
              <Settings2 className="h-3.5 w-3.5" /> Transform (optional)
            </h3>
            <div className="grid grid-cols-2 gap-3">
              <div className="space-y-1">
                <label className="text-caption text-muted-foreground">
                  Group by
                </label>
                {sourceTableColumns.length > 0 ? (
                  <select
                    value={groupBy}
                    onChange={(e) => setGroupBy(e.target.value)}
                    className={selectClass}
                  >
                    <option value="">None</option>
                    {sourceTableColumns.map((col) => (
                      <option key={col.column_name} value={col.column_name}>
                        {col.column_name}
                      </option>
                    ))}
                  </select>
                ) : (
                  <Input
                    value={groupBy}
                    onChange={(e) => setGroupBy(e.target.value)}
                    placeholder="created_at"
                    className="h-8 text-xs"
                  />
                )}
              </div>
              <div className="space-y-1">
                <label className="text-caption text-muted-foreground">
                  Time granularity
                </label>
                <select
                  value={timeGranularity}
                  onChange={(e) => setTimeGranularity(e.target.value)}
                  className={selectClass}
                >
                  {TIME_GRANULARITY_OPTIONS.map((opt) => (
                    <option key={opt.value} value={opt.value}>
                      {opt.label}
                    </option>
                  ))}
                </select>
              </div>
              <div className="space-y-1">
                <label className="text-caption text-muted-foreground">
                  Aggregation column
                </label>
                {sourceTableColumns.length > 0 ? (
                  <select
                    value={aggColumn}
                    onChange={(e) => setAggColumn(e.target.value)}
                    className={selectClass}
                  >
                    <option value="">None</option>
                    {sourceTableColumns.map((col) => (
                      <option key={col.column_name} value={col.column_name}>
                        {col.column_name}
                      </option>
                    ))}
                  </select>
                ) : (
                  <Input
                    value={aggColumn}
                    onChange={(e) => setAggColumn(e.target.value)}
                    placeholder="total"
                    className="h-8 text-xs"
                  />
                )}
              </div>
              <div className="space-y-1">
                <label className="text-caption text-muted-foreground">
                  Aggregation strategy
                </label>
                <select
                  value={aggStrategy}
                  onChange={(e) => setAggStrategy(e.target.value)}
                  className={selectClass}
                >
                  {AGG_STRATEGY_OPTIONS.map((opt) => (
                    <option key={opt.value} value={opt.value}>
                      {opt.label}
                    </option>
                  ))}
                </select>
              </div>
            </div>
          </section>

          <section className="rounded-lg border border-border bg-card p-4 space-y-3">
            <h3 className="text-xs font-medium uppercase tracking-wider text-muted-foreground flex items-center gap-2">
              <ArrowRight className="h-3.5 w-3.5" /> Sink
            </h3>
            <div className="space-y-1">
              <label className="text-caption text-muted-foreground">
                Destination table
              </label>
              <select
                value={sinkTable}
                onChange={(e) => setSinkTable(e.target.value)}
                className={selectClass}
              >
                <option value="">Select table...</option>
                {tables.map((t) => {
                  const key = `${t.table_schema ?? "public"}.${t.table_name}`;
                  const label = t.table_schema
                    ? `${t.table_schema}.${t.table_name}`
                    : t.table_name;
                  return (
                    <option key={key} value={t.table_name}>
                      {label}
                    </option>
                  );
                })}
              </select>
            </div>
          </section>

          <div className="flex items-center gap-3">
            <Button
              onClick={onRun}
              disabled={running || !clientName}
              className="h-9"
            >
              {running ? (
                <Loader2 className="h-3.5 w-3.5 animate-spin" />
              ) : (
                <Play className="h-3.5 w-3.5" />
              )}
              {running ? "Running..." : "Run Pipeline"}
            </Button>
            <Button
              variant="outline"
              size="sm"
              onClick={onViewJson}
              className="h-9 text-xs"
            >
              <FileText className="h-3.5 w-3.5 mr-1" /> View as JSON
            </Button>
          </div>

          {lastResult && (
            <section className="rounded-lg border border-success-border bg-success-subtle p-4 space-y-2 animate-slide-up">
              <div className="flex items-center gap-2">
                <CheckCircle2 className="h-4 w-4 text-success" />
                <span className="text-sm font-medium text-success">
                  Pipeline completed
                </span>
              </div>
              <div className="flex gap-4 text-xs text-muted-foreground">
                <span>
                  Fetched:{" "}
                  <strong className="text-foreground">
                    {lastResult.rows_fetched ?? 0}
                  </strong>
                </span>
                <span>
                  Inserted:{" "}
                  <strong className="text-foreground">
                    {lastResult.rows_inserted ?? 0}
                  </strong>
                </span>
                {(lastResult.errors?.length ?? 0) > 0 && (
                  <span className="text-destructive">
                    Errors: {lastResult.errors!.length}
                  </span>
                )}
              </div>
              {lastResult.data && lastResult.data.length > 0 && (
                <pre className="mt-2 max-h-50 overflow-auto rounded bg-muted p-3 font-mono text-caption text-muted-foreground">
                  {JSON.stringify(lastResult.data.slice(0, 10), null, 2)}
                </pre>
              )}
            </section>
          )}

          {lastError && (
            <section className="rounded-lg border border-destructive-border bg-destructive-subtle p-3 animate-slide-up">
              <div className="flex items-center gap-2">
                <AlertCircle className="h-3.5 w-3.5 text-destructive shrink-0" />
                <span className="text-xs font-medium text-destructive">
                  Pipeline failed
                </span>
              </div>
              <p className="text-body-sm text-destructive mt-1 wrap-break-word">
                {lastError}
              </p>
            </section>
          )}
        </div>
      </ScrollArea>
    </div>
  );
}
