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(/\/+$/, "");
}

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 currentJob = null;
  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 statusResponse = await fetch(
      `${backendApiUrl}/pipeline/status/${encodeURIComponent(shop)}`,
    );
    if (statusResponse.ok) {
      currentJob = await readJsonSafe(statusResponse);
    }
  } catch {
    currentJob = null;
  }

  return {
    shop,
    backendApiUrl,
    connection,
    currentJob,
  };
};

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 limit = limitValue ? Number(limitValue) : null;

  try {
    const response = await fetch(`${backendApiUrl}/pipeline/run`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        shop,
        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,
      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 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),
    ),
  );

  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>{job.step || "-"}</span>
        <span>{progressPercent}% complete</span>
      </div>
      <div className={styles.progressTrack}>
        <div
          className={styles.progressFill}
          style={{ width: `${progressPercent}%` }}
        />
      </div>

      <div className={styles.statGrid}>
        <div className={styles.statCard}>
          <span className={styles.statLabel}>Step</span>
          <strong>
            {job.stepIndex || 0}/{job.totalSteps || 6}
          </strong>
        </div>
        <div className={styles.statCard}>
          <span className={styles.statLabel}>Started</span>
          <strong>{job.startedAt ? new Date(job.startedAt).toLocaleString() : "-"}</strong>
        </div>
        <div className={styles.statCard}>
          <span className={styles.statLabel}>Updated</span>
          <strong>{job.updatedAt ? new Date(job.updatedAt).toLocaleString() : "-"}</strong>
        </div>
      </div>

      <div className={styles.detailCard}>
        <span className={styles.statLabel}>Detail</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}
    </div>
  );
}

export default function Index() {
  const { shop, backendApiUrl, connection, currentJob } = useLoaderData();
  const fetcher = useFetcher();
  const shopify = useAppBridge();
  const [job, setJob] = useState(currentJob);
  const setupUrl = `${backendApiUrl}/auth/login?shop=${encodeURIComponent(shop)}`;

  const isSubmitting =
    ["loading", "submitting"].includes(fetcher.state) &&
    fetcher.formMethod === "POST";

  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) {
      setJob({
        id: fetcher.data.jobId,
        status: "queued",
        step: "queued",
        stepIndex: 0,
        totalSteps: 6,
        detail: "Job queued",
      });
      shopify.toast.show("KYT import job started");
      return;
    }

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

  useEffect(() => {
    if (!job?.id) {
      return undefined;
    }

    let cancelled = false;

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

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

    return () => {
      cancelled = true;
      clearInterval(timer);
    };
  }, [backendApiUrl, job?.id]);

  return (
    <s-page heading="Race Nation Imports">
      <div className={styles.hero}>
        <div className={styles.heroCopy}>
          <p className={styles.kicker}>Import Center</p>
          <h2>Bring KYT products into your store from one simple dashboard.</h2>
          <p className={styles.heroText}>
            Start an import, follow the progress, and keep track of what is
            happening 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}>Import</span>
            <strong>{job ? "In progress" : "Not started"}</strong>
          </div>
        </div>
      </div>

      <div className={styles.grid}>
        <div className={styles.primaryColumn}>
          <s-section heading="Store Setup">
            <div className={styles.panelBody}>
              <div className={styles.inlineRow}>
                <span className={styles.statLabel}>Store status</span>
                <span
                  className={`${styles.statusPill} ${
                    connection?.status === 1 ? styles.success : styles.warning
                  }`}
                >
                  {connectionState}
                </span>
              </div>
              <div className={styles.detailCard}>
                <span className={styles.statLabel}>Message</span>
                <p>{connectionMessage}</p>
              </div>
              {connection?.status !== 1 ? (
                <div className={`${styles.detailCard} ${styles.warningCard}`}>
                  <span className={styles.statLabel}>What to do</span>
                  <p>Connect your store first, then start the import.</p>
                  <div className={styles.actionRow}>
                    <s-button variant="primary" onClick={openSetup}>
                      Connect store
                    </s-button>
                  </div>
                </div>
              ) : (
                <div className={`${styles.detailCard} ${styles.successCard}`}>
                  <span className={styles.statLabel}>Store connection</span>
                  <p>Your store is ready. You can start importing products now.</p>
                </div>
              )}
            </div>
          </s-section>

          <s-section
            heading="Start Product Import"
            description="Choose how much you want to import, then start the process."
          >
            <fetcher.Form method="post">
              <div className={styles.panelBody}>
                <s-text-field
                  label="Product limit"
                  name="limit"
                  type="number"
                  min="1"
                  details="Leave this empty to import all products, or enter a smaller number for a partial import."
                />
                <div className={styles.actionRow}>
                  <s-button
                    type="submit"
                    variant="primary"
                    {...(isSubmitting ? { loading: true } : {})}
                  >
                    Start import
                  </s-button>
                </div>
              </div>
            </fetcher.Form>
          </s-section>
        </div>

        <div className={styles.secondaryColumn}>
          <s-section heading="Import Progress">
            <JobSummary job={job} />
          </s-section>

          <s-section heading="What Happens Next">
            <div className={styles.stepList}>
              <div className={styles.stepItem}>1. Product information is collected.</div>
              <div className={styles.stepItem}>2. Product images are prepared.</div>
              <div className={styles.stepItem}>3. Images are uploaded to Shopify.</div>
              <div className={styles.stepItem}>4. Products are created or updated in your store.</div>
            </div>
          </s-section>
        </div>
      </div>
    </s-page>
  );
}

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