import { useEffect, useMemo, useState } from "react";
import { useFetcher, useLoaderData } from "react-router";
import { useAppBridge } from "@shopify/app-bridge-react";
import { boundary } from "@shopify/shopify-app-react-router/server";
import { authenticate } from "../shopify.server";
import styles from "../styles/app-dashboard.module.css";

function getBackendApiUrl() {
  return String(process.env.BACKEND_API_URL || "http://localhost:3002").replace(/\/+$/, "");
}

const FALLBACK_SOURCES = [{ sourceKey: "kyt", label: "KYT India" }];

function getJobIdForSource(shop, sourceKey = "kyt") {
  return sourceKey === "kyt" ? shop : `${shop}::${sourceKey}`;
}

async function readJsonSafe(response) {
  const text = await response.text();
  try {
    return text ? JSON.parse(text) : null;
  } catch {
    return { raw: text };
  }
}

export const loader = async ({ request }) => {
  const { session } = await authenticate.admin(request);
  const backendApiUrl = getBackendApiUrl();
  const shop = session.shop;

  let connection = null;
  let sources = FALLBACK_SOURCES;
  let jobsBySource = {};
  try {
    const response = await fetch(
      `${backendApiUrl}/shops/${encodeURIComponent(shop)}`,
    );
    connection = await readJsonSafe(response);
  } catch (error) {
    connection = {
      status: 0,
      message: `Backend unavailable: ${error.message}`,
    };
  }

  try {
    const sourcesResponse = await fetch(`${backendApiUrl}/pipeline/sources`);
    if (sourcesResponse.ok) {
      const payload = await readJsonSafe(sourcesResponse);
      if (Array.isArray(payload?.sources) && payload.sources.length) {
        sources = payload.sources;
      }
    }
  } catch {
    sources = FALLBACK_SOURCES;
  }

  await Promise.all(
    sources.map(async (source) => {
      try {
        const jobId = getJobIdForSource(shop, source.sourceKey);
        const statusResponse = await fetch(
          `${backendApiUrl}/pipeline/status/${encodeURIComponent(jobId)}`,
        );
        if (statusResponse.ok) {
          jobsBySource[source.sourceKey] = await readJsonSafe(statusResponse);
        }
      } catch {
        jobsBySource[source.sourceKey] = null;
      }
    }),
  );

  if (!Object.keys(jobsBySource).length) {
    jobsBySource = {};
  }

  return {
    shop,
    backendApiUrl,
    connection,
    sources,
    jobsBySource,
  };
};

export const action = async ({ request }) => {
  const { session } = await authenticate.admin(request);
  const formData = await request.formData();
  const backendApiUrl = getBackendApiUrl();
  const shop = session.shop;
  const limitValue = String(formData.get("limit") || "").trim();
  const source = String(formData.get("source") || "kyt").trim() || "kyt";
  const limit = limitValue ? Number(limitValue) : null;

  try {
    const response = await fetch(`${backendApiUrl}/pipeline/run`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        shop,
        source,
        limit: Number.isFinite(limit) && limit > 0 ? limit : null,
      }),
    });

    const payload = await readJsonSafe(response);
    if (!response.ok) {
      return {
        ok: false,
        error: payload?.error || "Failed to start import job.",
      };
    }

    return {
      ok: true,
      jobId: payload.jobId,
      shop,
      source: payload.source || source,
      limit: payload.limit,
      backendApiUrl,
    };
  } catch (error) {
    return {
      ok: false,
      error: error.message,
    };
  }
};

function FieldState({ fields }) {
  if (!fields) {
    return <s-text tone="subdued">Your store is not ready yet.</s-text>;
  }

  return (
    <s-stack direction="block" gap="tight">
      {Object.entries(fields).map(([key, value]) => (
        <s-inline-stack key={key} gap="base" alignItems="center">
          <s-text>{key}</s-text>
          <s-badge tone={value === "present" ? "success" : "critical"}>
            {value}
          </s-badge>
        </s-inline-stack>
      ))}
    </s-stack>
  );
}

function formatCounter(done, total) {
  if (Number.isFinite(done) && Number.isFinite(total) && total > 0) {
    return `${done} / ${total}`;
  }

  if (Number.isFinite(done)) {
    return String(done);
  }

  return "-";
}

function getStageState(job, bucket) {
  const activeStepMap = {
    download: "downloadImages",
    watermark: "watermarkImages",
    upload: "uploadImagesToShopifyFiles",
    convert: "convertToShopifyReady",
    shopify: "upsertToShopify",
    details: "fetchWebsiteData",
  };

  if (job?.status === "error") {
    return "error";
  }

  if (job?.status === "done") {
    return "done";
  }

  if (job?.step === activeStepMap[bucket]) {
    return "active";
  }

  const stats = job?.liveStats || {};
  if (stats[bucket]?.total || stats[bucket]?.done || stats.stageSummaries?.[activeStepMap[bucket]]) {
    return "done";
  }

  return "pending";
}

const STEP_LABELS = {
  queued: "Queued",
  starting: "Preparing import",
  fetchWebsiteData: "Collecting catalog data",
  downloadImages: "Downloading product images",
  watermarkImages: "Applying watermarks",
  uploadImagesToShopifyFiles: "Uploading images to Shopify",
  convertToShopifyReady: "Preparing Shopify product data",
  upsertToShopify: "Creating or updating products",
  completed: "Import completed",
};

function getStepLabel(step) {
  return STEP_LABELS[step] || step || "-";
}

function formatDateTime(value) {
  if (!value) {
    return "-";
  }

  return new Date(value).toLocaleString();
}

function formatElapsed(startedAt, updatedAt) {
  if (!startedAt) {
    return "-";
  }

  const startMs = new Date(startedAt).getTime();
  const endMs = updatedAt ? new Date(updatedAt).getTime() : Date.now();

  if (!Number.isFinite(startMs) || !Number.isFinite(endMs) || endMs < startMs) {
    return "-";
  }

  const seconds = Math.floor((endMs - startMs) / 1000);
  const hours = Math.floor(seconds / 3600);
  const minutes = Math.floor((seconds % 3600) / 60);
  const remainingSeconds = seconds % 60;

  if (hours > 0) {
    return `${hours}h ${minutes}m ${remainingSeconds}s`;
  }

  if (minutes > 0) {
    return `${minutes}m ${remainingSeconds}s`;
  }

  return `${remainingSeconds}s`;
}

function parseRecentActivity(entry) {
  const rawLine = String(entry?.line || "");
  const line = rawLine.replace(/^\[(log|info|warn|error)\]\s*/i, "").trim();

  const watermarkMatch = line.match(/^\[WATERMARK\]\s+(\d+)\/(\d+)\s+processed/i);
  if (watermarkMatch) {
    return {
      title: "Watermark progress updated",
      detail: `${watermarkMatch[1]} of ${watermarkMatch[2]} images have been watermarked.`,
      tone: "progress",
    };
  }

  const imageDownloadMatch = line.match(/^\[IMAGES\]\s+(\d+)\/(\d+)\s+processed/i);
  if (imageDownloadMatch) {
    return {
      title: "Image download progress updated",
      detail: `${imageDownloadMatch[1]} of ${imageDownloadMatch[2]} product images have been downloaded.`,
      tone: "progress",
    };
  }

  const uploadProgressMatch = line.match(/^\[IMG-UPLOAD\]\s+(\d+)\/(\d+)\s+processed\s+\|\s+uploaded=(\d+)\s+skipped=(\d+)\s+failed=(\d+)/i);
  if (uploadProgressMatch) {
    return {
      title: "Shopify image upload progress updated",
      detail: `${uploadProgressMatch[3]} of ${uploadProgressMatch[2]} images are ready in Shopify files. ${uploadProgressMatch[4]} skipped and ${uploadProgressMatch[5]} failed so far.`,
      tone: "progress",
    };
  }

  const uploadOkMatch = line.match(/^\[IMG-UPLOAD-OK\]\s+(.+?)\s+\|\s+(.+?)\s+\|\s+fileId=(.+?)\s+\|\s+status=([A-Z]+)/i);
  if (uploadOkMatch) {
    return {
      title: "Image uploaded to Shopify",
      detail: `${uploadOkMatch[2]} is now in Shopify files with status ${uploadOkMatch[4]}.`,
      tone: "success",
    };
  }

  const uploadSkipMatch = line.match(/^\[IMG-UPLOAD-SKIP\]\s+(.+?)\s+\|\s+(.+?)\s+\|\s+(.+)/i);
  if (uploadSkipMatch) {
    return {
      title: "Image reuse detected",
      detail: `${uploadSkipMatch[2]} was already available, so upload was skipped.`,
      tone: "neutral",
    };
  }

  const uploadFailMatch = line.match(/^\[IMG-UPLOAD-FAIL\]\s+(.+?)\s+\|\s+(.+?)\s+->\s+(.+)/i);
  if (uploadFailMatch) {
    return {
      title: "Image upload needs attention",
      detail: `${uploadFailMatch[1]} could not be uploaded. ${uploadFailMatch[3]}`,
      tone: "error",
    };
  }

  const shopifyProgressMatch = line.match(/^\[SHOPIFY\]\s+(\d+)\/(\d+)\s+processed\s+\|\s+created=(\d+)\s+updated=(\d+)\s+failed=(\d+)/i);
  if (shopifyProgressMatch) {
    return {
      title: "Product sync progress updated",
      detail: `${shopifyProgressMatch[1]} of ${shopifyProgressMatch[2]} products processed. ${shopifyProgressMatch[3]} created, ${shopifyProgressMatch[4]} updated, ${shopifyProgressMatch[5]} failed.`,
      tone: "progress",
    };
  }

  const shopifyFailMatch = line.match(/^\[SHOPIFY-FAIL\]\s+(.+?)\s+->\s+(.+)/i);
  if (shopifyFailMatch) {
    return {
      title: "Product sync needs attention",
      detail: `${shopifyFailMatch[1]} could not be synced. ${shopifyFailMatch[2]}`,
      tone: "error",
    };
  }

  const detailProgressMatch = line.match(/^\[DETAIL\]\s+(\d+)\/(\d+)\s+completed/i);
  if (detailProgressMatch) {
    return {
      title: "Product details collected",
      detail: `${detailProgressMatch[1]} of ${detailProgressMatch[2]} products now have detailed catalog data.`,
      tone: "progress",
    };
  }

  const imageFailMatch = line.match(/^\[IMAGE-FAIL\]\s+(.+?)\s+\|\s+(.+?)\s+->\s+(.+)/i);
  if (imageFailMatch) {
    return {
      title: "Image download needs attention",
      detail: `${imageFailMatch[1]} has a download issue. ${imageFailMatch[3]}`,
      tone: "error",
    };
  }

  const watermarkFailMatch = line.match(/^\[WATERMARK-FAIL\]\s+(.+?)\s+->\s+(.+)/i);
  if (watermarkFailMatch) {
    return {
      title: "Watermark step needs attention",
      detail: `${watermarkFailMatch[1]} could not be watermarked. ${watermarkFailMatch[2]}`,
      tone: "error",
    };
  }

  const pipelineStepMatch = line.match(/^\[PIPELINE\s+(\d+)\/(\d+)\]\s+(.+)/i);
  if (pipelineStepMatch) {
    return {
      title: `Pipeline step ${pipelineStepMatch[1]} of ${pipelineStepMatch[2]}`,
      detail: pipelineStepMatch[3],
      tone: "neutral",
    };
  }

  return {
    title: "Import activity updated",
    detail: line,
    tone: "neutral",
  };
}

function JobSummary({ job }) {
  if (!job) {
    return (
      <div className={styles.emptyPanel}>
        <div className={styles.emptyGlow}></div>
        <h3>No import in progress</h3>
        <p>Start an import to see the live progress and current step here.</p>
      </div>
    );
  }

  const progressPercent = Math.max(
    0,
    Math.min(
      100,
      Math.round(((job.stepIndex || 0) / (job.totalSteps || 6)) * 100),
    ),
  );
  const liveStats = job.liveStats || {};
  const recentLogs = Array.isArray(job.logs)
    ? job.logs.slice(-8).reverse().map((entry) => ({
        ...entry,
        parsed: parseRecentActivity(entry),
      }))
    : [];
  const summarySteps = job.summary?.steps || {};
  const downloadStats = liveStats.download || {};
  const watermarkStats = liveStats.watermark || {};
  const uploadStats = liveStats.upload || {};
  const shopifyStats = liveStats.shopify || {};
  const detailStats = liveStats.details || {};
  const activeStepLabel = job.detail || "Import running";
  const currentStepLabel = getStepLabel(job.step);
  const analyticsCards = [
    {
      key: "download",
      label: "Downloaded",
      value: formatCounter(
        downloadStats.done ?? summarySteps.downloadImages?.downloaded,
        downloadStats.total ?? summarySteps.downloadImages?.totalImagesFound,
      ),
      meta: `${downloadStats.skipped ?? summarySteps.downloadImages?.skipped ?? 0} skipped • ${downloadStats.failed ?? summarySteps.downloadImages?.failed ?? 0} failed`,
      tone: "sunrise",
    },
    {
      key: "watermark",
      label: "Watermarked",
      value: formatCounter(
        watermarkStats.done ?? summarySteps.watermarkImages?.processed,
        watermarkStats.total ?? summarySteps.watermarkImages?.totalImagesFound,
      ),
      meta: `${watermarkStats.skipped ?? summarySteps.watermarkImages?.skipped ?? summarySteps.watermarkImages?.skippedCount ?? 0} skipped • ${watermarkStats.failed ?? summarySteps.watermarkImages?.failed ?? 0} failed`,
      tone: "ice",
    },
    {
      key: "upload",
      label: "Uploaded",
      value: formatCounter(
        uploadStats.uploaded ?? summarySteps.uploadImagesToShopifyFiles?.uploaded,
        uploadStats.total ?? summarySteps.uploadImagesToShopifyFiles?.totalTasks,
      ),
      meta: `${uploadStats.skipped ?? summarySteps.uploadImagesToShopifyFiles?.skipped ?? 0} skipped • ${uploadStats.failed ?? summarySteps.uploadImagesToShopifyFiles?.failed ?? 0} failed`,
      tone: "mint",
    },
    {
      key: "shopify",
      label: "Products synced",
      value: formatCounter(
        shopifyStats.done ?? summarySteps.upsertToShopify?.processed,
        shopifyStats.total ?? summarySteps.upsertToShopify?.total,
      ),
      meta: `${shopifyStats.created ?? summarySteps.upsertToShopify?.created ?? 0} created • ${shopifyStats.updated ?? summarySteps.upsertToShopify?.updated ?? 0} updated`,
      tone: "navy",
    },
  ].filter((card) => card.value !== "-");
  const highlightCards = [
    {
      key: "activity",
      label: "Current activity",
      value: activeStepLabel,
      meta: `Step ${job.stepIndex || 0} of ${job.totalSteps || 6}`,
    },
    {
      key: "details",
      label: "Product details",
      value: formatCounter(
        detailStats.done ?? summarySteps.fetchWebsiteData?.analysis?.detailFetchedNow,
        detailStats.total ?? summarySteps.fetchWebsiteData?.analysis?.totalProductsUnique,
      ),
      meta: `${summarySteps.fetchWebsiteData?.analysis?.cachedDetailReused ?? 0} cached reused`,
    },
    {
      key: "ready",
      label: "Images ready in Shopify",
      value: String(
        liveStats.uploadedOk ??
          summarySteps.uploadImagesToShopifyFiles?.uploaded ??
          0,
      ),
      meta: `${uploadStats.failed ?? summarySteps.uploadImagesToShopifyFiles?.failed ?? 0} upload issues`,
    },
    {
      key: "success",
      label: "Sync success rate",
      value: shopifyStats.successRate
        ? `${shopifyStats.successRate}%`
        : summarySteps.upsertToShopify?.successRate
          ? `${summarySteps.upsertToShopify.successRate}%`
          : job.status === "done"
            ? "100%"
            : "Running",
      meta: job.status === "error" ? "Needs attention" : "Based on product sync stage",
    },
  ];
  const stageItems = [
    {
      key: "details",
      title: "Fetch product details",
      state: getStageState(job, "details"),
      value: formatCounter(
        detailStats.done ?? summarySteps.fetchWebsiteData?.analysis?.detailFetchedNow,
        detailStats.total ?? summarySteps.fetchWebsiteData?.analysis?.totalProductsUnique,
      ),
      meta: `${summarySteps.fetchWebsiteData?.analysis?.cachedDetailReused ?? 0} reused from cache`,
    },
    {
      key: "download",
      title: "Download product images",
      state: getStageState(job, "download"),
      value: formatCounter(
        downloadStats.done ?? summarySteps.downloadImages?.downloaded,
        downloadStats.total ?? summarySteps.downloadImages?.totalImagesFound,
      ),
      meta: `${downloadStats.failed ?? summarySteps.downloadImages?.failed ?? 0} failed`,
    },
    {
      key: "watermark",
      title: "Apply watermark",
      state: getStageState(job, "watermark"),
      value: formatCounter(
        watermarkStats.done ?? summarySteps.watermarkImages?.processed,
        watermarkStats.total ?? summarySteps.watermarkImages?.totalImagesFound,
      ),
      meta: `${watermarkStats.failed ?? summarySteps.watermarkImages?.failed ?? 0} failed`,
    },
    {
      key: "upload",
      title: "Upload images to Shopify",
      state: getStageState(job, "upload"),
      value: formatCounter(
        uploadStats.uploaded ?? summarySteps.uploadImagesToShopifyFiles?.uploaded,
        uploadStats.total ?? summarySteps.uploadImagesToShopifyFiles?.totalTasks,
      ),
      meta: `${uploadStats.skipped ?? summarySteps.uploadImagesToShopifyFiles?.skipped ?? 0} skipped • ${uploadStats.failed ?? summarySteps.uploadImagesToShopifyFiles?.failed ?? 0} failed`,
    },
    {
      key: "shopify",
      title: "Create or update products",
      state: getStageState(job, "shopify"),
      value: formatCounter(
        shopifyStats.done ?? summarySteps.upsertToShopify?.processed,
        shopifyStats.total ?? summarySteps.upsertToShopify?.total,
      ),
      meta: `${shopifyStats.created ?? summarySteps.upsertToShopify?.created ?? 0} created • ${shopifyStats.updated ?? summarySteps.upsertToShopify?.updated ?? 0} updated`,
    },
  ];

  return (
    <div className={styles.jobPanel}>
      <div className={styles.jobHeader}>
        <div>
          <p className={styles.eyebrow}>Current import</p>
          <h3 className={styles.panelTitle}>{job.id}</h3>
        </div>
        <span
          className={`${styles.statusPill} ${
            job.status === "done"
              ? styles.success
              : job.status === "error"
                ? styles.error
                : styles.active
          }`}
        >
          {job.status}
        </span>
      </div>

      <div className={styles.progressMeta}>
        <span>{currentStepLabel}</span>
        <span>{progressPercent}% complete</span>
      </div>
      <div className={styles.progressTrack}>
        <div
          className={styles.progressFill}
          style={{ width: `${progressPercent}%` }}
        />
      </div>

      <div className={styles.progressOverviewGrid}>
        <div className={styles.progressOverviewCard}>
          <span className={styles.statLabel}>Current stage</span>
          <strong className={styles.progressOverviewValue}>{currentStepLabel}</strong>
          <span className={styles.progressOverviewMeta}>
            Step {job.stepIndex || 0} of {job.totalSteps || 6}
          </span>
        </div>
        <div className={styles.progressOverviewCard}>
          <span className={styles.statLabel}>Started</span>
          <strong className={styles.progressOverviewValue}>
            {formatDateTime(job.startedAt)}
          </strong>
          <span className={styles.progressOverviewMeta}>Import start time</span>
        </div>
        <div className={styles.progressOverviewCard}>
          <span className={styles.statLabel}>Last update</span>
          <strong className={styles.progressOverviewValue}>
            {formatDateTime(job.updatedAt)}
          </strong>
          <span className={styles.progressOverviewMeta}>Latest backend activity</span>
        </div>
        <div className={styles.progressOverviewCard}>
          <span className={styles.statLabel}>Elapsed</span>
          <strong className={styles.progressOverviewValue}>
            {formatElapsed(job.startedAt, job.updatedAt)}
          </strong>
          <span className={styles.progressOverviewMeta}>Time spent on this run</span>
        </div>
      </div>

      {analyticsCards.length ? (
        <div className={styles.analyticsGrid}>
          {analyticsCards.map((card) => (
            <div
              key={card.key}
              className={`${styles.analyticsCard} ${styles[`analytics${card.tone[0].toUpperCase()}${card.tone.slice(1)}`]}`}
            >
              <span className={styles.analyticsLabel}>{card.label}</span>
              <strong className={styles.analyticsValue}>{card.value}</strong>
              <span className={styles.analyticsMeta}>{card.meta}</span>
            </div>
          ))}
        </div>
      ) : null}

      <div className={styles.highlightGrid}>
        {highlightCards.map((card) => (
          <div key={card.key} className={styles.highlightCard}>
            <span className={styles.highlightLabel}>{card.label}</span>
            <strong className={styles.highlightValue}>{card.value}</strong>
            <span className={styles.highlightMeta}>{card.meta}</span>
          </div>
        ))}
      </div>

      <div className={styles.timelineCard}>
        <div className={styles.timelineHeader}>
          <span className={styles.statLabel}>Stage progress</span>
          <strong className={styles.timelineTitle}>Live pipeline board</strong>
          <span className={styles.timelineSubtitle}>
            Each row shows the current count for that stage while the import is running.
          </span>
        </div>
        <div className={styles.stageList}>
          {stageItems.map((stage) => (
            <div key={stage.key} className={styles.stageItem}>
              <div className={styles.stageMain}>
                <span
                  className={`${styles.stageDot} ${
                    stage.state === "done"
                      ? styles.stageDone
                      : stage.state === "active"
                        ? styles.stageActive
                        : stage.state === "error"
                          ? styles.stageError
                          : styles.stagePending
                  }`}
                />
                <div>
                  <strong className={styles.stageTitle}>{stage.title}</strong>
                  <p className={styles.stageMeta}>{stage.meta}</p>
                </div>
              </div>
              <span className={styles.stageValue}>{stage.value}</span>
            </div>
          ))}
        </div>
      </div>

      <div className={styles.statGrid}>
        <div className={styles.statCard}>
          <span className={styles.statLabel}>Job status</span>
          <strong>
            {job.status || "-"}
          </strong>
        </div>
        <div className={styles.statCard}>
          <span className={styles.statLabel}>Completion</span>
          <strong>{progressPercent}%</strong>
        </div>
        <div className={styles.statCard}>
          <span className={styles.statLabel}>Job key</span>
          <strong>{job.id}</strong>
        </div>
      </div>

      <div className={styles.detailCard}>
        <span className={styles.statLabel}>What is happening now</span>
        <p>{job.detail || "-"}</p>
      </div>

      {job.error ? (
        <div className={`${styles.detailCard} ${styles.errorCard}`}>
          <span className={styles.statLabel}>Error</span>
          <p>{job.error}</p>
        </div>
      ) : null}

      {job.summary ? (
        <div className={styles.jsonCard}>
          <span className={styles.statLabel}>Summary</span>
          <pre style={{ margin: 0, whiteSpace: "pre-wrap" }}>
            <code>{JSON.stringify(job.summary, null, 2)}</code>
          </pre>
        </div>
      ) : null}

      {recentLogs.length ? (
        <div className={styles.logCard}>
          <span className={styles.statLabel}>Recent activity</span>
          <div className={styles.logList}>
            {recentLogs.map((entry, index) => (
              <div
                key={`${entry.at}-${index}`}
                className={`${styles.logLine} ${
                  entry.parsed?.tone === "success"
                    ? styles.logSuccess
                    : entry.parsed?.tone === "error"
                      ? styles.logError
                      : entry.parsed?.tone === "progress"
                        ? styles.logProgress
                        : styles.logNeutral
                }`}
              >
                <span className={styles.logTime}>
                  {entry.at ? new Date(entry.at).toLocaleTimeString() : ""}
                </span>
                <strong className={styles.logTitle}>{entry.parsed?.title || "Activity"}</strong>
                <p className={styles.logDetail}>{entry.parsed?.detail || entry.line}</p>
              </div>
            ))}
          </div>
        </div>
      ) : null}
    </div>
  );
}

export default function Index() {
  const { shop, backendApiUrl, connection, sources, jobsBySource } = useLoaderData();
  const fetcher = useFetcher();
  const shopify = useAppBridge();
  const sourceList = sources?.length ? sources : FALLBACK_SOURCES;
  const [activeSource, setActiveSource] = useState(sourceList[0]?.sourceKey || "kyt");
  const [sourceJobs, setSourceJobs] = useState(jobsBySource || {});
  const activeSourceConfig =
    sourceList.find((source) => source.sourceKey === activeSource) || sourceList[0] || FALLBACK_SOURCES[0];
  const job = sourceJobs[activeSourceConfig.sourceKey] || null;
  const activeJobId = job?.id || null;
  const setupUrl = `${backendApiUrl}/auth/login?shop=${encodeURIComponent(shop)}`;

  const isSubmitting =
    ["loading", "submitting"].includes(fetcher.state) &&
    fetcher.formMethod === "POST" &&
    String(fetcher.formData?.get("source") || "") === activeSourceConfig.sourceKey;

  const runningSources = useMemo(() => {
    return new Set(
      Object.entries(sourceJobs || {})
        .filter(([, sourceJob]) => sourceJob && !["done", "error"].includes(sourceJob.status))
        .map(([sourceKey]) => sourceKey),
    );
  }, [sourceJobs]);

  const connectionState = useMemo(() => {
    if (connection?.status === 1) {
      return "Ready";
    }
    return "Setup needed";
  }, [connection]);

  const connectionMessage = useMemo(() => {
    if (connection?.status === 1) {
      return "Your store is connected and ready for import.";
    }

    if (String(connection?.message || "").toLowerCase().includes("fetch failed")) {
      return "We could not reach the import service right now.";
    }

    if (String(connection?.message || "").toLowerCase().includes("shop not found")) {
      return "This store still needs to be connected before imports can run.";
    }

    return "This store is not ready yet.";
  }, [connection]);

  const openSetup = () => {
    if (typeof window !== "undefined") {
      window.top.location.href = setupUrl;
    }
  };

  useEffect(() => {
    if (!fetcher.data) {
      return;
    }

    if (fetcher.data.ok && fetcher.data.jobId) {
      const sourceKey = fetcher.data.source || activeSourceConfig.sourceKey;
      setActiveSource(sourceKey);
      setSourceJobs((current) => ({
        ...current,
        [sourceKey]: {
          id: fetcher.data.jobId,
          status: "queued",
          step: "queued",
          stepIndex: 0,
          totalSteps: 6,
          detail: "Job queued",
          payload: {
            source: sourceKey,
            shop,
            limit: fetcher.data.limit,
          },
        },
      }));
      const sourceLabel =
        sourceList.find((source) => source.sourceKey === sourceKey)?.label || sourceKey;
      shopify.toast.show(`${sourceLabel} import job started`);
      return;
    }

    if (fetcher.data.error) {
      shopify.toast.show(fetcher.data.error, { isError: true });
    }
  }, [activeSourceConfig.sourceKey, fetcher.data, shop, shopify, sourceList]);

  useEffect(() => {
    const sourceKey = activeSourceConfig.sourceKey;
    const jobId = activeJobId;

    if (!jobId) {
      return undefined;
    }

    let cancelled = false;

    async function pollStatus() {
      try {
        const response = await fetch(
          `${backendApiUrl}/pipeline/status/${encodeURIComponent(jobId)}`,
        );
        const payload = await readJsonSafe(response);
        if (!cancelled && response.ok) {
          setSourceJobs((current) => ({
            ...current,
            [sourceKey]: payload,
          }));
        }
      } catch (error) {
        if (!cancelled) {
          setSourceJobs((current) => ({
            ...current,
            [sourceKey]: current[sourceKey]
              ? {
                  ...current[sourceKey],
                  detail: `Status polling failed: ${error.message}`,
                }
              : current[sourceKey],
          }));
        }
      }
    }

    pollStatus();
    const timer = setInterval(pollStatus, 3000);

    return () => {
      cancelled = true;
      clearInterval(timer);
    };
  }, [activeJobId, activeSourceConfig.sourceKey, backendApiUrl, shop]);

  return (
    <s-page heading="Race Nation Imports">
      <div className={styles.hero}>
        <div className={styles.heroCopy}>
          <p className={styles.kicker}>Import Center</p>
          <h2>Manage every product source from one import dashboard.</h2>
          <p className={styles.heroText}>
            Pick a source, start its import, and follow the progress without
            leaving Shopify.
          </p>
        </div>
        <div className={styles.heroMetrics}>
          <div className={styles.metricTile}>
            <span className={styles.metricLabel}>Store</span>
            <strong>{shop}</strong>
          </div>
          <div className={styles.metricTile}>
            <span className={styles.metricLabel}>Status</span>
            <strong>{connectionState}</strong>
          </div>
          <div className={styles.metricTile}>
            <span className={styles.metricLabel}>Active source</span>
            <strong>{activeSourceConfig.label}</strong>
          </div>
        </div>
      </div>

      <div className={styles.dashboardShell}>
        <div className={styles.sourceTabsShell}>
          <div className={styles.sourceTabs} role="tablist" aria-label="Import sources">
            {sourceList.map((source) => {
              const sourceJob = sourceJobs[source.sourceKey];
              const isActive = source.sourceKey === activeSourceConfig.sourceKey;
              const isRunning = runningSources.has(source.sourceKey);
              return (
                <button
                  key={source.sourceKey}
                  type="button"
                  role="tab"
                  aria-selected={isActive}
                  className={`${styles.sourceTab} ${isActive ? styles.sourceTabActive : ""}`}
                  onClick={() => setActiveSource(source.sourceKey)}
                >
                  <span className={styles.sourceTabTitle}>{source.label}</span>
                  <span
                    className={`${styles.sourceTabStatus} ${
                      sourceJob?.status === "done"
                        ? styles.sourceTabDone
                        : sourceJob?.status === "error"
                          ? styles.sourceTabError
                          : isRunning
                            ? styles.sourceTabRunning
                            : ""
                    }`}
                  >
                    {sourceJob?.status || "ready"}
                  </span>
                </button>
              );
            })}
          </div>
        </div>

        <div className={styles.controlRow}>
          <div className={styles.controlCard}>
            <div className={styles.controlHeader}>
              <div>
                <span className={styles.statLabel}>Store setup</span>
                <h3 className={styles.controlTitle}>Connection status</h3>
              </div>
              <span
                className={`${styles.statusPill} ${
                  connection?.status === 1 ? styles.success : styles.warning
                }`}
              >
                {connectionState}
              </span>
            </div>
            <p className={styles.controlText}>{connectionMessage}</p>
            {connection?.status !== 1 ? (
              <div className={styles.actionRow}>
                <s-button variant="primary" onClick={openSetup}>
                  Connect store
                </s-button>
              </div>
            ) : null}
          </div>

          <div className={styles.controlCard}>
            <div className={styles.controlHeader}>
              <div>
                <span className={styles.statLabel}>Import action</span>
                <h3 className={styles.controlTitle}>{activeSourceConfig.label} import</h3>
              </div>
            </div>
            <p className={styles.controlText}>
              Launch this source independently and track its live sync below.
            </p>
            <fetcher.Form method="post">
              <input type="hidden" name="source" value={activeSourceConfig.sourceKey} />
              <div className={styles.controlForm}>
                <div className={styles.actionRow}>
                  <s-button
                    type="submit"
                    variant="primary"
                    {...(connection?.status !== 1 ? { disabled: true } : {})}
                    {...(isSubmitting ? { loading: true } : {})}
                  >
                    Start {activeSourceConfig.label}
                  </s-button>
                </div>
              </div>
            </fetcher.Form>
          </div>
        </div>

        <div className={styles.mainPanel}>
          <div className={styles.mainPanelHeader}>
            <div>
              <span className={styles.statLabel}>Live dashboard</span>
              <h3 className={styles.controlTitle}>{activeSourceConfig.label} progress</h3>
            </div>
          </div>
          <JobSummary job={job} />
        </div>
      </div>
    </s-page>
  );
}

export const headers = (headersArgs) => {
  return boundary.headers(headersArgs);
};
