import type { ActionFunctionArgs, HeadersFunction, LoaderFunctionArgs } from "react-router";
import { Form, useActionData, useLoaderData } from "react-router";
import { boundary } from "@shopify/shopify-app-react-router/server";
import { authenticate } from "../../shopify.server";
import db from "../../db.server";
import { moneyInr, toPaise } from "../../utils";
import { SET_ORDER_METAFIELDS } from "../../shopify-graphql.server";
import { adminGraphqlFromSession } from "../../shopify-graphql.server";

export const loader = async ({ request, params }: LoaderFunctionArgs) => {
  const { session } = await authenticate.admin(request);
  const order = await db.deliveryOrder.findFirst({ where: { id: params.id, shop: session.shop } });
  if (!order) throw new Response("Delivery order not found", { status: 404 });
  return { order };
};

export const action = async ({ request, params }: ActionFunctionArgs) => {
  const { session } = await authenticate.admin(request);
  const form = await request.formData();
  const intent = String(form.get("intent") || "");
  const existing = await db.deliveryOrder.findFirst({ where: { id: params.id, shop: session.shop } });
  if (!existing) return { ok: false, message: "Delivery order not found." };

  if (intent === "update-charge") {
    if (existing.status === "COLLECTED") return { ok: false, message: "A collected delivery charge cannot be changed." };
    const charge = String(form.get("charge") || "").trim();
    if (!charge || !/^(?:\d+)(?:\.\d{1,2})?$/.test(charge)) {
      return { ok: false, message: "Enter a valid delivery charge amount." };
    }
    const updated = await db.deliveryOrder.update({
      where: { id: existing.id },
      data: { chargePaise: toPaise(charge) },
    });
    if (existing.orderGid) {
      await adminGraphqlFromSession(session.shop, session.accessToken, SET_ORDER_METAFIELDS, {
        metafields: [
          { ownerId: existing.orderGid, namespace: "$app", key: "delivery_charge", type: "number_decimal", value: String(updated.chargePaise / 100) },
        ],
      }).catch(() => undefined);
    }
    return { ok: true, message: `Delivery charge updated to ${moneyInr(updated.chargePaise)}.` };
  }

  if (intent === "collect") {
    const method = String(form.get("collectionMethod") || "OTHER");
    const collectedBy = String(form.get("collectedBy") || "").trim();
    const notes = String(form.get("notes") || "").trim();
    if (!collectedBy) return { ok: false, message: "Enter who collected the delivery charge." };
    const updated = await db.deliveryOrder.update({ where: { id: existing.id }, data: { status: "COLLECTED", collectionMethod: method, collectedBy, collectedAt: new Date(), notes } });
    if (existing.orderGid) {
      await adminGraphqlFromSession(session.shop, session.accessToken, SET_ORDER_METAFIELDS, {
        metafields: [
          { ownerId: existing.orderGid, namespace: "$app", key: "delivery_charge", type: "number_decimal", value: String(updated.chargePaise / 100) },
          { ownerId: existing.orderGid, namespace: "$app", key: "delivery_charge_status", type: "single_line_text_field", value: "COLLECTED" },
          { ownerId: existing.orderGid, namespace: "$app", key: "delivery_collection_method", type: "single_line_text_field", value: method },
          { ownerId: existing.orderGid, namespace: "$app", key: "delivery_collected_at", type: "date_time", value: updated.collectedAt?.toISOString() || new Date().toISOString() },
        ],
      }).catch(() => undefined);
    }
    return { ok: true, message: `${moneyInr(updated.chargePaise)} marked as collected.` };
  }

  if (intent === "waive") {
    const updated = await db.deliveryOrder.update({ where: { id: existing.id }, data: { status: "WAIVED", collectionMethod: null, collectedBy: null, collectedAt: null } });
    if (existing.orderGid) await adminGraphqlFromSession(session.shop, session.accessToken, SET_ORDER_METAFIELDS, { metafields: [{ ownerId: existing.orderGid, namespace: "$app", key: "delivery_charge_status", type: "single_line_text_field", value: "WAIVED" }] }).catch(() => undefined);
    return { ok: true, message: `${moneyInr(updated.chargePaise)} marked as waived.` };
  }

  return { ok: false, message: "Unknown action." };
};

export default function DeliveryOrderDetail() {
  const { order } = useLoaderData<typeof loader>();
  const action = useActionData<typeof action>();
  const collected = order.status === "COLLECTED";
  return (
    <div className="sb-page">
      <s-page heading={`Delivery charge ${order.orderName}`}>
        {action?.message ? <s-banner tone={action.ok ? "success" : "critical"}>{action.message}</s-banner> : null}
        <div className="sb-grid sb-grid-2" style={{marginTop: 16}}>
          <div className="sb-card"><h3>Collection</h3><div className="sb-kpi">{moneyInr(order.chargePaise)}</div>
            {!collected ? (
              <Form method="post" className="sb-row" style={{marginBottom: 12}}>
                <input type="hidden" name="intent" value="update-charge" />
                <input className="sb-input" name="charge" type="number" min="0" step="0.01" defaultValue={(order.chargePaise / 100).toFixed(2)} aria-label="Delivery charge" />
                <s-button type="submit">Update charge</s-button>
              </Form>
            ) : null}
            <p>Status: <strong>{order.status}</strong></p><p>Method: {order.collectionMethod || "—"}</p><p>Collected by: {order.collectedBy || "—"}</p><p>Collected at: {order.collectedAt ? new Date(order.collectedAt).toLocaleString("en-IN") : "—"}</p><p>Notes: {order.notes || "—"}</p></div>
          <div className="sb-card"><h3>Customer / order</h3><p><strong>{order.orderName}</strong></p><p>{order.customerName || "—"}</p><p>{order.customerEmail || "—"}</p><p>PIN: {order.pincode || "—"}</p><p>Shopify order ID: {order.orderId}</p></div>
        </div>

        {!collected && order.status !== "WAIVED" ? (
          <div className="sb-card" style={{marginTop: 16}}>
            <h3>Mark delivery charge collected</h3>
            <Form method="post" className="sb-form-grid">
              <input type="hidden" name="intent" value="collect" />
              <label>Collection method<select name="collectionMethod" className="sb-select" defaultValue="UPI"><option value="UPI">UPI</option><option value="CASH">Cash</option><option value="OTHER">Other</option></select></label>
              <label>Collected by<input className="sb-input" name="collectedBy" placeholder="Delivery staff name" /></label>
              <label>Notes<textarea className="sb-textarea" name="notes" placeholder="Optional collection note" /></label>
              <div className="sb-row"><s-button type="submit" variant="primary">Mark as collected</s-button></div>
            </Form>
            <Form method="post" style={{marginTop: 12}}><input type="hidden" name="intent" value="waive" /><s-button type="submit" variant="tertiary">Waive delivery charge</s-button></Form>
          </div>
        ) : null}
      </s-page>
    </div>
  );
}

export const headers: HeadersFunction = (headersArgs) => boundary.headers(headersArgs);
