"use client";

import Link from "next/link";
import { useEffect, useRef, useState, type PointerEvent } from "react";

import { ArrowUpRightIcon, Badge, ProgressBar } from "@/components/dashboard-ui";
import { PropertyMap } from "@/components/property-map";
import type {
  ComplianceItem,
  MessageThread,
  Property,
  WorkOrder,
} from "@/lib/property-data-uk";
import {
  formatCompactCurrency,
  formatCurrency,
  formatDate,
  formatPercent,
  getPropertyCollectionRate,
  getPropertyOccupancy,
} from "@/lib/property-data-uk";
import { buildLocalValuation, type PropertyValuation } from "@/lib/valuation";

type OverviewPropertyFlickerProps = {
  properties: Property[];
  workOrders: WorkOrder[];
  complianceItems: ComplianceItem[];
  messageThreads: MessageThread[];
};

function clampIndex(index: number, length: number) {
  if (index < 0) {
    return length - 1;
  }

  if (index >= length) {
    return 0;
  }

  return index;
}

function countOpenRepairs(propertyId: string, workOrders: WorkOrder[]) {
  return workOrders.filter(
    (order) => order.propertyId === propertyId && order.status !== "Resolved",
  ).length;
}

function countComplianceDue(propertyId: string, complianceItems: ComplianceItem[]) {
  return complianceItems.filter(
    (item) => item.propertyId === propertyId && item.status !== "Completed",
  ).length;
}

function countUnreadMessages(propertyId: string, messageThreads: MessageThread[]) {
  return messageThreads
    .filter((thread) => thread.propertyId === propertyId)
    .reduce((sum, thread) => sum + thread.unread, 0);
}

function isInteractiveTarget(target: EventTarget | null) {
  return target instanceof HTMLElement
    ? Boolean(target.closest("a, button, input, label, select, textarea"))
    : false;
}

function PropertyProfileArrowIcon({ direction }: { direction: "previous" | "next" }) {
  return (
    <svg
      aria-hidden="true"
      className="h-5 w-5"
      fill="none"
      viewBox="0 0 24 24"
    >
      <path
        d={direction === "previous" ? "m15 18-6-6 6-6" : "m9 6 6 6-6 6"}
        stroke="currentColor"
        strokeLinecap="round"
        strokeLinejoin="round"
        strokeWidth="2.2"
      />
    </svg>
  );
}

export function OverviewPropertyFlicker({
  properties,
  workOrders,
  complianceItems,
  messageThreads,
}: OverviewPropertyFlickerProps) {
  const [activeIndex, setActiveIndex] = useState(0);
  const [valuation, setValuation] = useState<PropertyValuation | null>(null);
  const [valuationLoading, setValuationLoading] = useState(false);
  const dragStartX = useRef<number | null>(null);
  const dragStartY = useRef<number | null>(null);
  const dragStartedOnInteractive = useRef(false);
  const property = properties[activeIndex] ?? properties[0];

  useEffect(() => {
    if (!property) {
      return;
    }

    const controller = new AbortController();

    async function loadValuation() {
      setValuationLoading(true);

      try {
        const response = await fetch(`/api/zoopla/valuation/${property.slug}`, {
          signal: controller.signal,
        });

        if (!response.ok) {
          setValuation(buildLocalValuation(property));
          return;
        }

        setValuation((await response.json()) as PropertyValuation);
      } catch {
        if (!controller.signal.aborted) {
          setValuation(buildLocalValuation(property));
        }
      } finally {
        if (!controller.signal.aborted) {
          setValuationLoading(false);
        }
      }
    }

    setValuation(null);
    loadValuation();

    return () => controller.abort();
  }, [property]);

  if (!property) {
    return null;
  }

  const occupancy = getPropertyOccupancy(property);
  const collectionRate = getPropertyCollectionRate(property);
  const openRepairs = countOpenRepairs(property.id, workOrders);
  const complianceDue = countComplianceDue(property.id, complianceItems);
  const unreadMessages = countUnreadMessages(property.id, messageThreads);
  const arrearsPressure =
    property.arrearsAmount > 0
      ? `${formatCurrency(property.arrearsAmount)} arrears`
      : "No arrears logged";

  function goToPrevious() {
    setActiveIndex((current) => clampIndex(current - 1, properties.length));
  }

  function goToNext() {
    setActiveIndex((current) => clampIndex(current + 1, properties.length));
  }

  function handleSlideStart(event: PointerEvent<HTMLElement>) {
    if (event.pointerType === "mouse" && event.button !== 0) {
      return;
    }

    dragStartedOnInteractive.current = isInteractiveTarget(event.target);
    dragStartX.current = event.clientX;
    dragStartY.current = event.clientY;
  }

  function clearSlideState() {
    dragStartX.current = null;
    dragStartY.current = null;
    dragStartedOnInteractive.current = false;
  }

  function handleSlideEnd(event: PointerEvent<HTMLElement>) {
    if (
      dragStartX.current === null ||
      dragStartY.current === null ||
      dragStartedOnInteractive.current
    ) {
      clearSlideState();
      return;
    }

    const deltaX = event.clientX - dragStartX.current;
    const deltaY = event.clientY - dragStartY.current;
    const isHorizontalSwipe = Math.abs(deltaX) > 54 && Math.abs(deltaX) > Math.abs(deltaY) * 1.25;

    clearSlideState();

    if (!isHorizontalSwipe) {
      return;
    }

    if (deltaX < 0) {
      goToNext();
    } else {
      goToPrevious();
    }
  }

  return (
    <section
      className="relative overflow-hidden border-y border-border py-8"
      onPointerCancel={clearSlideState}
      onPointerDown={handleSlideStart}
      onPointerUp={handleSlideEnd}
    >
      <div className="pointer-events-none absolute right-8 top-8 h-44 w-44 rounded-full bg-accent-soft/60 blur-3xl" />
      <div className="pointer-events-none absolute bottom-6 left-6 h-36 w-36 rounded-full bg-primary-soft/70 blur-3xl" />
      <button
        aria-label={`Show previous property before ${property.name}`}
        className="absolute left-1 top-56 z-20 grid h-11 w-11 -translate-y-1/2 place-items-center rounded-full border border-border bg-surface/90 text-foreground shadow-[0_16px_36px_rgba(20,53,105,0.12)] backdrop-blur transition hover:border-primary/45 hover:text-primary sm:left-2 sm:top-60 sm:h-12 sm:w-12"
        onClick={goToPrevious}
        type="button"
      >
        <PropertyProfileArrowIcon direction="previous" />
      </button>
      <button
        aria-label={`Show next property after ${property.name}`}
        className="absolute right-1 top-56 z-20 grid h-11 w-11 -translate-y-1/2 place-items-center rounded-full border border-primary bg-primary text-white shadow-[0_16px_36px_rgba(20,53,105,0.18)] transition hover:bg-primary/90 sm:right-2 sm:top-60 sm:h-12 sm:w-12"
        onClick={goToNext}
        type="button"
      >
        <PropertyProfileArrowIcon direction="next" />
      </button>

      <div className="relative flex cursor-grab select-none touch-pan-y flex-col gap-9 px-12 active:cursor-grabbing sm:px-14 xl:grid xl:grid-cols-[minmax(0,0.92fr)_minmax(0,1.08fr)] xl:items-end xl:px-16">
        <div>
          <p className="font-mono text-xs uppercase tracking-[0.3em] text-muted">
            Property profile
          </p>
          <div className="mt-4">
            <div className="flex flex-col gap-5 sm:gap-7 lg:flex-row lg:items-start lg:justify-between">
              <div className="min-w-0 flex-1">
                <div className="flex flex-wrap items-center gap-2">
                  <Badge tone="teal">{property.type}</Badge>
                  <Badge tone="neutral">
                    {activeIndex + 1} of {properties.length}
                  </Badge>
                </div>
                <h2 className="mt-4 max-w-3xl text-4xl font-semibold tracking-tight text-foreground md:text-6xl">
                  {property.name}
                </h2>
                <p className="mt-3 max-w-2xl text-sm leading-6 text-muted">
                  {property.address}, {property.city}, {property.postcode}
                </p>
              </div>
              <div className="w-full shrink-0 lg:w-[22rem] xl:w-[24rem]">
                <PropertyMap
                  lat={property.coordinates.lat}
                  lng={property.coordinates.lng}
                  title={property.name}
                />
              </div>
            </div>

          </div>
        </div>

        <div>
          <p className="max-w-3xl text-base leading-7 text-muted md:text-lg">
            {property.tagline}
          </p>

          <dl className="mt-6 grid gap-x-8 gap-y-5 sm:grid-cols-2 lg:grid-cols-3">
            <div className="border-l border-border pl-4">
              <dt className="text-xs uppercase tracking-[0.2em] text-muted">
                Monthly rent roll
              </dt>
              <dd className="mt-2 text-2xl font-semibold text-foreground">
                {formatCompactCurrency(property.monthlyRentRoll)}
              </dd>
            </div>
            <div className="border-l border-border pl-4">
              <dt className="text-xs uppercase tracking-[0.2em] text-muted">
                Collected
              </dt>
              <dd className="mt-2 text-2xl font-semibold text-foreground">
                {formatPercent(collectionRate)}
              </dd>
            </div>
            <div className="border-l border-border pl-4">
              <dt className="text-xs uppercase tracking-[0.2em] text-muted">
                Arrears
              </dt>
              <dd className="mt-2 text-2xl font-semibold text-foreground">
                {formatCompactCurrency(property.arrearsAmount)}
              </dd>
            </div>
            <div className="border-l border-border pl-4">
              <dt className="text-xs uppercase tracking-[0.2em] text-muted">
                Occupancy
              </dt>
              <dd className="mt-2 text-2xl font-semibold text-foreground">
                {property.occupiedUnits}/{property.units}
              </dd>
            </div>
            <div className="border-l border-border pl-4">
              <dt className="text-xs uppercase tracking-[0.2em] text-muted">
                Next inspection
              </dt>
              <dd className="mt-2 text-2xl font-semibold text-foreground">
                {formatDate(property.nextInspection)}
              </dd>
            </div>
            <div className="border-l border-border pl-4">
              <dt className="text-xs uppercase tracking-[0.2em] text-muted">
                EPC / council tax
              </dt>
              <dd className="mt-2 text-2xl font-semibold text-foreground">
                {property.epcRating} / {property.councilTaxBand}
              </dd>
            </div>
          </dl>

          <div className="mt-6 rounded-[26px] border border-border bg-white/72 p-5 shadow-[0_18px_44px_rgba(20,53,105,0.08)]">
            <div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
              <div>
                <p className="font-mono text-xs uppercase tracking-[0.24em] text-primary">
                  Zoopla valuation
                </p>
                <p className="mt-2 text-3xl font-semibold tracking-tight text-foreground">
                  {valuationLoading || !valuation
                    ? "Loading valuation"
                    : formatCurrency(valuation.estimate)}
                </p>
              </div>
              <Badge
                tone={
                  valuation?.connected ? "success" : valuation ? "amber" : "neutral"
                }
              >
                {valuation?.connected
                  ? "Zoopla API live"
                  : valuation
                    ? "Connect Zoopla"
                    : "Checking"}
              </Badge>
            </div>

            {valuation ? (
              <>
                <dl className="mt-5 grid gap-3 text-sm text-muted sm:grid-cols-3">
                  <div className="rounded-[18px] border border-border bg-surface/80 p-4">
                    <dt>Estimate range</dt>
                    <dd className="mt-1 font-semibold text-foreground">
                      {formatCompactCurrency(valuation.lowEstimate)} -{" "}
                      {formatCompactCurrency(valuation.highEstimate)}
                    </dd>
                  </div>
                  <div className="rounded-[18px] border border-border bg-surface/80 p-4">
                    <dt>Rental estimate</dt>
                    <dd className="mt-1 font-semibold text-foreground">
                      {formatCompactCurrency(valuation.rentalEstimate)} / mo
                    </dd>
                  </div>
                  <div className="rounded-[18px] border border-border bg-surface/80 p-4">
                    <dt>Confidence</dt>
                    <dd className="mt-1 font-semibold text-foreground">
                      {valuation.confidence}
                    </dd>
                  </div>
                </dl>
                <p className="mt-4 text-sm leading-6 text-muted">{valuation.note}</p>
              </>
            ) : (
              <p className="mt-5 text-sm text-muted">
                Checking the server-side valuation route for this property.
              </p>
            )}
          </div>

          <div className="mt-6 grid gap-4 md:grid-cols-[1fr_1fr_auto] md:items-end">
            <div>
              <div className="flex items-center justify-between text-sm">
                <span className="font-semibold text-foreground">Occupancy</span>
                <span className="text-muted">{formatPercent(occupancy)}</span>
              </div>
              <div className="mt-2">
                <ProgressBar value={occupancy} tone="teal" />
              </div>
            </div>
            <div>
              <div className="flex items-center justify-between text-sm">
                <span className="font-semibold text-foreground">Rent collection</span>
                <span className="text-muted">{arrearsPressure}</span>
              </div>
              <div className="mt-2">
                <ProgressBar value={collectionRate} tone="amber" />
              </div>
            </div>
            <Link
              className="inline-flex items-center justify-center gap-2 rounded-full border border-border px-4 py-2.5 text-sm font-semibold text-foreground transition hover:border-primary/35 hover:text-primary"
              href={`/properties/${property.slug}`}
            >
              Open record <ArrowUpRightIcon className="h-4 w-4" />
            </Link>
          </div>

          <div className="mt-5 flex flex-wrap gap-2">
            <Badge tone={openRepairs > 0 ? "amber" : "success"}>
              {openRepairs} open repairs
            </Badge>
            <Badge tone={complianceDue > 0 ? "red" : "success"}>
              {complianceDue} compliance due
            </Badge>
            <Badge tone={unreadMessages > 0 ? "amber" : "neutral"}>
              {unreadMessages} unread messages
            </Badge>
            <Badge tone="neutral">{property.localAuthority}</Badge>
          </div>

          <div className="mt-7 flex justify-center gap-2">
            {properties.map((item, index) => (
              <button
                aria-current={index === activeIndex ? "true" : undefined}
                aria-label={`Show ${item.name}`}
                className={[
                  "h-2.5 rounded-full transition",
                  index === activeIndex
                    ? "w-10 bg-primary"
                    : "w-2.5 bg-muted/35 hover:bg-muted/60",
                ].join(" ")}
                key={item.id}
                onClick={() => setActiveIndex(index)}
                type="button"
              />
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}
