import { type ReactNode } from "react";
import { Link } from "@tanstack/react-router";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { Crosshair, X, ArrowRight, TrendingUp, TrendingDown, Minus, Star, Plus, Check, RefreshCw, ExternalLink, Activity, Loader2, XCircle } from "lucide-react";
import { Button } from "@/components/ui/button";
import type { Competitor } from "@/lib/briefing.functions";
import type { Hotel } from "@/lib/hotel";
import { addCustomAction, useCustomActions, type CustomAction } from "@/lib/customActions";
import { useDismissedActions } from "@/lib/dismissedActions";
import { useFocusedCompetitors } from "@/hooks/useFocusedCompetitors";
import { getCompetitorLive, refreshCompetitorLive, type CompetitorLiveSnapshot } from "@/lib/competitorLive.functions";
import { supabase } from "@/integrations/supabase/client";
import { Bookmark, BookmarkCheck } from "lucide-react";

async function authHeaders(): Promise<Record<string, string>> {
  const { data } = await supabase.auth.getSession();
  const token = data.session?.access_token;
  return token ? { Authorization: `Bearer ${token}` } : {};
}

type Suggestion = {
  title: string;
  why: string;
  category: CustomAction["category"];
  urgency: CustomAction["urgency"];
};

function buildSuggestions(hotel: Hotel, c: Competitor, currency: string): Suggestion[] {
  const out: Suggestion[] = [];
  const myAdr = hotel.adr_weekday ?? 0;
  const compAdr = c.estimated_adr_myr;
  const myOcc = hotel.occupancy_pct ?? 0;
  const compOcc = c.estimated_occupancy_pct;

  // Pricing
  if (myAdr > 0 && compAdr > 0) {
    const delta = ((compAdr - myAdr) / myAdr) * 100;
    if (delta >= 8) {
      out.push({
        title: `Test +${Math.min(Math.round(delta / 2), 12)}% rate lift on weekday ADR`,
        why: `${c.name} prices ${currency} ${compAdr.toFixed(0)} (${delta.toFixed(0)}% above you). Capture pricing power before they do.`,
        category: "Pricing",
        urgency: "this_week",
      });
    } else if (delta <= -8) {
      out.push({
        title: `Run a 7-day rate match vs. ${c.name}`,
        why: `${c.name} undercuts you by ${Math.abs(delta).toFixed(0)}%. Match or add value (free breakfast) to defend share.`,
        category: "Pricing",
        urgency: "today",
      });
    }
  }

  // Occupancy gap
  if (compOcc - myOcc >= 10) {
    out.push({
      title: `Push direct booking promo to close occupancy gap`,
      why: `${c.name} runs at ${compOcc.toFixed(0)}% vs your ${myOcc}%. Launch a direct-channel offer to recover demand.`,
      category: "Marketing",
      urgency: "this_week",
    });
  }

  // Promotions
  if ((c.promotions?.length ?? 0) > 0) {
    const top = c.promotions[0];
    out.push({
      title: `Counter "${top.title}" on ${top.channel}`,
      why: `${c.name} is actively promoting on ${top.channel}${top.ends ? ` until ${top.ends}` : ""}. Mirror or differentiate on the same channel.`,
      category: "Distribution",
      urgency: "today",
    });
  }

  // Reviews
  if (typeof c.review_score === "number" && c.review_score >= 8.5) {
    out.push({
      title: `Audit guest experience to lift review score`,
      why: `${c.name} averages ${c.review_score.toFixed(1)}/10 on ${c.review_source ?? "OTA"}. Review your last 30 reviews — fix the top complaint.`,
      category: "Guest",
      urgency: "this_month",
    });
  }

  // Unique offerings
  if ((c.unique_offerings?.length ?? 0) > 0) {
    out.push({
      title: `Differentiate against ${c.unique_offerings[0]}`,
      why: `${c.name} markets "${c.unique_offerings.slice(0, 2).join(", ")}". Highlight your own strengths in OTA copy & website hero.`,
      category: "Marketing",
      urgency: "this_week",
    });
  }

  // Recent move
  if (c.recent_move) {
    out.push({
      title: `Respond to competitor's recent move`,
      why: `${c.name}: ${c.recent_move}`,
      category: "Pricing",
      urgency: "today",
    });
  }

  return out.slice(0, 6);
}

export function CompetitorFocus({
  hotel,
  competitor,
  currency,
  onClose,
}: {
  hotel: Hotel;
  competitor: Competitor;
  currency: string;
  onClose: () => void;
}) {
  const suggestions = buildSuggestions(hotel, competitor, currency);
  const { items: customActions } = useCustomActions();
  const focused = useFocusedCompetitors(hotel.id);
  const compKey = `${competitor.name}|${competitor.distance_km.toFixed(2)}`;
  const isTracked = focused.isTracked(compKey);
  const myAdr = hotel.adr_weekday ?? 0;
  const myOcc = hotel.occupancy_pct ?? 0;
  const adrDelta = myAdr > 0 ? ((competitor.estimated_adr_myr - myAdr) / myAdr) * 100 : 0;
  const occDelta = competitor.estimated_occupancy_pct - myOcc;

  return (
    <section className="mb-8 rounded-2xl border border-brand/40 bg-gradient-to-br from-brand-soft/30 to-card p-5 shadow-[var(--shadow-elegant)] sm:p-7">
      <div className="mb-5 flex flex-wrap items-start justify-between gap-3">
        <div className="min-w-0 flex-1">
          <div className="inline-flex items-center gap-2 text-xs uppercase tracking-[0.18em] text-accent">
            <Crosshair className="h-3.5 w-3.5" /> Focused competitor
          </div>
          <h2 className="mt-1 break-words font-serif text-2xl font-medium text-brand sm:text-3xl">
            {hotel.hotel_name} <span className="text-muted-foreground">vs.</span> {competitor.name}
          </h2>
          <p className="mt-1 text-sm text-muted-foreground">
            Side-by-side comparison and actions you can take to win.
          </p>
        </div>
        <div className="flex shrink-0 flex-wrap items-center gap-1.5">
          <Button
            size="sm"
            variant={isTracked ? "secondary" : "outline"}
            onClick={() =>
              isTracked
                ? focused.untrack(compKey)
                : focused.track({
                    competitor_key: compKey,
                    competitor_name: competitor.name,
                    snapshot: {
                      distance_km: competitor.distance_km,
                      estimated_adr_myr: competitor.estimated_adr_myr,
                      estimated_occupancy_pct: competitor.estimated_occupancy_pct,
                      star_rating: competitor.star_rating ?? null,
                      review_score: competitor.review_score ?? null,
                    },
                  })
            }
            className="gap-1.5"
          >
            {isTracked ? (
              <>
                <BookmarkCheck className="h-4 w-4 text-emerald-600" /> Tracked
              </>
            ) : (
              <>
                <Bookmark className="h-4 w-4" /> Track
              </>
            )}
          </Button>
          <Button size="sm" variant="ghost" onClick={onClose} className="gap-1.5">
            <X className="h-4 w-4" /> Unfocus
          </Button>
        </div>
      </div>

      {/* Comparison grid */}
      <div className="grid gap-3 sm:grid-cols-2">
        <ComparisonRow
          label={`ADR (${currency})`}
          mine={myAdr ? `${currency} ${myAdr.toFixed(0)}` : "—"}
          theirs={`${currency} ${competitor.estimated_adr_myr.toFixed(0)}`}
          deltaPct={adrDelta}
          higherIsBetter={true}
        />
        <ComparisonRow
          label="Occupancy"
          mine={myOcc ? `${myOcc}%` : "—"}
          theirs={`${competitor.estimated_occupancy_pct.toFixed(0)}%`}
          deltaPct={occDelta}
          deltaSuffix="pp"
          higherIsBetter={true}
        />
        <ComparisonRow
          label="Star rating"
          mine={hotel.star_rating ? renderStars(hotel.star_rating) : "—"}
          theirs={competitor.star_rating ? renderStars(competitor.star_rating) : "—"}
        />
        <ComparisonRow
          label="Property type"
          mine={hotel.property_type ?? "—"}
          theirs={competitor.property_type ?? "—"}
        />
        <ComparisonRow
          label="Target guest"
          mine={hotel.target_guest ?? "—"}
          theirs={competitor.target_guest ?? "—"}
        />
        <ComparisonRow
          label="Reviews"
          mine="—"
          theirs={
            typeof competitor.review_score === "number"
              ? `${competitor.review_score.toFixed(1)}/10 (${competitor.review_count ?? "?"} on ${competitor.review_source ?? "OTA"})`
              : "—"
          }
        />
        <ComparisonRow
          label="Active promotions"
          mine="—"
          theirs={
            (competitor.promotions?.length ?? 0) > 0
              ? competitor.promotions.map((p) => `${p.title} (${p.channel})`).join("; ")
              : "None"
          }
        />
        <ComparisonRow
          label="Unique offerings"
          mine={hotel.amenities.slice(0, 3).join(", ") || "—"}
          theirs={(competitor.unique_offerings ?? []).slice(0, 3).join(", ") || "—"}
        />
      </div>

      {/* Recent move */}
      {competitor.recent_move ? (
        <div className="mt-5 flex items-start gap-2 rounded-xl bg-brand-soft/40 px-4 py-3 text-sm text-brand">
          <ArrowRight className="mt-0.5 h-4 w-4 shrink-0" />
          <span>
            <span className="font-semibold">Recent move:</span> {competitor.recent_move}
          </span>
        </div>
      ) : null}

      {/* Live OTA market data */}
      <LiveMarketPanel hotelId={hotel.id} competitorName={competitor.name} location={hotel.location} currency={currency} />

      {/* Suggestions */}
      <div className="mt-6">
        <div className="mb-3 flex flex-wrap items-end justify-between gap-2">
          <div>
            <h3 className="font-serif text-lg font-medium text-foreground">Suggested actions</h3>
            <p className="text-xs text-muted-foreground">
              Add any to your plan — they'll show up on the Actions page.
            </p>
          </div>
          <Button size="sm" variant="outline" asChild>
            <Link to="/actions">
              View Actions <ArrowRight className="ml-1 h-3.5 w-3.5" />
            </Link>
          </Button>
        </div>

        {suggestions.length === 0 ? (
          <div className="rounded-xl border bg-muted/30 px-4 py-6 text-center text-sm text-muted-foreground">
            No major gaps detected vs. this competitor. Keep monitoring.
          </div>
        ) : (
          <div className="grid gap-3 md:grid-cols-2">
            {suggestions.map((s, i) => (
              <SuggestionCard
                key={i}
                suggestion={s}
                competitorName={competitor.name}
                added={customActions.some(
                  (a) => a.title === s.title && a.source_label === `vs. ${competitor.name}`,
                )}
              />
            ))}
          </div>
        )}
      </div>
    </section>
  );
}

function SuggestionCard({
  suggestion,
  competitorName,
  added,
}: {
  suggestion: Suggestion;
  competitorName: string;
  added: boolean;
}) {
  const urgencyColor = {
    today: "text-destructive",
    this_week: "text-amber-700",
    this_month: "text-muted-foreground",
  }[suggestion.urgency];
  const dismissed = useDismissedActions();
  const dismissKey = `competitor:${competitorName}:${suggestion.title}`;
  if (dismissed.has(dismissKey)) {
    return (
      <div className="flex items-center justify-between gap-3 rounded-xl border border-dashed bg-muted/20 px-3 py-2 text-sm text-muted-foreground">
        <span className="line-through">{suggestion.title}</span>
        <Button size="sm" variant="ghost" className="h-7 gap-1 text-xs" onClick={() => dismissed.restore(dismissKey)}>
          Restore
        </Button>
      </div>
    );
  }

  return (
    <div className="rounded-xl border bg-card p-4">
      <div className="mb-1.5 flex flex-wrap items-center justify-between gap-x-3 gap-y-1">
        <div className="flex flex-wrap items-center gap-x-3 gap-y-1">
          <span className="text-[10px] font-medium uppercase tracking-wider text-accent">
            {suggestion.category}
          </span>
          <span
            className={`text-[10px] font-medium uppercase tracking-wider ${urgencyColor}`}
          >
            {suggestion.urgency.replace("_", " ")}
          </span>
        </div>
        <Button size="sm" variant="ghost" className="h-7 gap-1 px-2 text-xs text-muted-foreground" onClick={() => dismissed.dismiss(dismissKey)}>
          <XCircle className="h-3.5 w-3.5" /> Dismiss
        </Button>
      </div>
      <h4 className="font-serif text-base font-medium text-foreground">{suggestion.title}</h4>
      <p className="mt-1 text-sm leading-relaxed text-muted-foreground">{suggestion.why}</p>
      <div className="mt-3 flex items-center gap-2">
        {added ? (
          <Button size="sm" variant="outline" asChild>
            <Link to="/actions">
              <Check className="mr-1.5 h-3.5 w-3.5 text-emerald-600" /> Added — view plan
            </Link>
          </Button>
        ) : (
          <Button
            size="sm"
            onClick={() =>
              addCustomAction({
                title: suggestion.title,
                why: suggestion.why,
                category: suggestion.category,
                urgency: suggestion.urgency,
                source_label: `vs. ${competitorName}`,
              })
            }
          >
            <Plus className="mr-1.5 h-3.5 w-3.5" /> Add to plan
          </Button>
        )}
      </div>
    </div>
  );
}

function ComparisonRow({
  label,
  mine,
  theirs,
  deltaPct,
  deltaSuffix = "%",
  higherIsBetter,
}: {
  label: string;
  mine: ReactNode;
  theirs: ReactNode;
  deltaPct?: number;
  deltaSuffix?: string;
  higherIsBetter?: boolean;
}) {
  let deltaNode = null;
  if (typeof deltaPct === "number" && Number.isFinite(deltaPct) && Math.abs(deltaPct) >= 0.5) {
    const compHigher = deltaPct > 0;
    const goodForMe = higherIsBetter ? !compHigher : compHigher;
    const Icon = compHigher ? TrendingUp : TrendingDown;
    const cls = goodForMe ? "text-emerald-700" : "text-destructive";
    deltaNode = (
      <span className={`inline-flex items-center gap-1 text-xs font-medium ${cls}`}>
        <Icon className="h-3 w-3" />
        {compHigher ? "+" : ""}
        {deltaPct.toFixed(0)}
        {deltaSuffix} vs. you
      </span>
    );
  } else if (deltaPct === 0) {
    deltaNode = (
      <span className="inline-flex items-center gap-1 text-xs text-muted-foreground">
        <Minus className="h-3 w-3" /> Inline
      </span>
    );
  }

  return (
    <div className="rounded-xl border bg-card/60 p-3">
      <div className="text-[10px] uppercase tracking-wider text-muted-foreground">{label}</div>
      <div className="mt-1 grid grid-cols-2 gap-3">
        <div>
          <div className="text-[10px] text-muted-foreground">You</div>
          <div className="text-sm font-medium text-foreground">{mine}</div>
        </div>
        <div>
          <div className="text-[10px] text-muted-foreground">Them</div>
          <div className="text-sm font-medium text-foreground">{theirs}</div>
        </div>
      </div>
      {deltaNode ? <div className="mt-2">{deltaNode}</div> : null}
    </div>
  );
}

function renderStars(n: number) {
  const count = Math.round(n);
  return (
    <span className="inline-flex items-center gap-0.5 text-amber-600">
      {Array.from({ length: count }).map((_, i) => (
        <Star key={i} className="h-3 w-3 fill-current" />
      ))}
    </span>
  );
}

function LiveMarketPanel({
  hotelId,
  competitorName,
  location,
  currency,
}: {
  hotelId: string;
  competitorName: string;
  location: string;
  currency: string;
}) {
  const qc = useQueryClient();
  const queryKey = ["competitor_live", hotelId, competitorName] as const;

  const { data, isLoading } = useQuery({
    queryKey,
    queryFn: async () =>
      getCompetitorLive({ data: { hotelId, competitorName }, headers: await authHeaders() }),
    staleTime: 60_000,
  });

  const refresh = useMutation({
    mutationFn: async () =>
      refreshCompetitorLive({
        data: { hotelId, competitorName, location, force: true },
        headers: await authHeaders(),
      }),
    onSuccess: (snap) => qc.setQueryData(queryKey, snap),
  });

  const rawSnap = data as CompetitorLiveSnapshot | null;
  const snap = rawSnap
    ? {
        ...rawSnap,
        price_data: rawSnap.price_data ?? { avg_price: null, currency: null },
        scarcity_data:
          rawSnap.scarcity_data ?? { rooms_left_badges: 0, sold_out_days: 0, days_checked: 0, occupancy_proxy_pct: null },
        reviews_data:
          rawSnap.reviews_data ?? { total_reviews: null, rating: null, reviews_per_month: null, source: null },
        sources: rawSnap.sources ?? [],
      }
    : null;
  const isStale = snap ? Date.now() - new Date(snap.scraped_at).getTime() > 24 * 60 * 60 * 1000 : false;

  return (
    <section className="mt-6 rounded-2xl border border-accent/30 bg-card p-5 shadow-[var(--shadow-elegant)] sm:p-6">
      <div className="mb-4 flex flex-wrap items-center justify-between gap-3">
        <div>
          <div className="inline-flex items-center gap-2 text-xs uppercase tracking-[0.18em] text-accent">
            <Activity className="h-3.5 w-3.5" /> Live OTA market data
          </div>
          <h3 className="mt-1 font-serif text-lg font-medium text-foreground">
            Scraped from Booking.com, Agoda & Google
          </h3>
          {snap?.scraped_at ? (
            <p className="text-xs text-muted-foreground">
              Last updated {new Date(snap.scraped_at).toLocaleString()}
              {isStale ? " · stale" : ""}
            </p>
          ) : null}
        </div>
        <Button
          size="sm"
          variant="outline"
          disabled={refresh.isPending}
          onClick={() => refresh.mutate()}
        >
          {refresh.isPending ? (
            <Loader2 className="mr-1.5 h-3.5 w-3.5 animate-spin" />
          ) : (
            <RefreshCw className="mr-1.5 h-3.5 w-3.5" />
          )}
          {snap ? "Refresh now" : "Fetch live data"}
        </Button>
      </div>

      {isLoading ? (
        <div className="text-sm text-muted-foreground">Loading…</div>
      ) : !snap ? (
        <div className="rounded-xl border bg-muted/30 px-4 py-6 text-sm text-muted-foreground">
          No live data yet. Click <strong>Fetch live data</strong> to scrape this competitor's
          current OTA prices, scarcity signals (a proxy for occupancy) and review velocity.
          A daily background job will keep it fresh after that.
        </div>
      ) : (
        <>
          {snap.error ? (
            <div className="mb-3 rounded-xl border border-amber-500/30 bg-amber-50 px-3 py-2 text-xs text-amber-900 dark:bg-amber-950/30 dark:text-amber-200">
              ⚠ {snap.error}
            </div>
          ) : null}

          <div className="grid gap-3 sm:grid-cols-3">
            {/* Price */}
            <div className="rounded-xl border bg-card/60 p-4">
              <div className="text-[10px] uppercase tracking-wider text-muted-foreground">
                Avg nightly rate
              </div>
              <div className="mt-1 font-serif text-2xl font-medium text-brand">
                {snap.price_data.avg_price
                  ? `${snap.price_data.currency ?? currency} ${snap.price_data.avg_price.toFixed(0)}`
                  : "—"}
              </div>
              <div className="mt-1.5 space-y-0.5 text-xs text-muted-foreground">
                {snap.price_data.booking?.price ? (
                  <div>Booking.com: {snap.price_data.booking.currency ?? ""} {snap.price_data.booking.price}</div>
                ) : null}
                {snap.price_data.agoda?.price ? (
                  <div>Agoda: {snap.price_data.agoda.currency ?? ""} {snap.price_data.agoda.price}</div>
                ) : null}
                {!snap.price_data.booking?.price && !snap.price_data.agoda?.price ? (
                  <div>No price found on listings</div>
                ) : null}
              </div>
            </div>

            {/* Scarcity proxy */}
            <div className="rounded-xl border bg-card/60 p-4">
              <div className="text-[10px] uppercase tracking-wider text-muted-foreground">
                Demand signal (occupancy proxy)
              </div>
              <div className="mt-1 font-serif text-2xl font-medium text-brand">
                {snap.scarcity_data.occupancy_proxy_pct != null
                  ? `~${snap.scarcity_data.occupancy_proxy_pct}%`
                  : "—"}
              </div>
              <div className="mt-1.5 space-y-0.5 text-xs text-muted-foreground">
                <div>{snap.scarcity_data.rooms_left_badges} "rooms left" badges</div>
                <div>{snap.scarcity_data.sold_out_days} sold-out hits</div>
                <div className="opacity-70">OTAs never expose real occupancy</div>
              </div>
            </div>

            {/* Reviews */}
            <div className="rounded-xl border bg-card/60 p-4">
              <div className="text-[10px] uppercase tracking-wider text-muted-foreground">
                Review velocity
              </div>
              <div className="mt-1 font-serif text-2xl font-medium text-brand">
                {snap.reviews_data.reviews_per_month
                  ? `${snap.reviews_data.reviews_per_month}/mo`
                  : "—"}
              </div>
              <div className="mt-1.5 space-y-0.5 text-xs text-muted-foreground">
                {snap.reviews_data.total_reviews ? (
                  <div>{snap.reviews_data.total_reviews.toLocaleString()} total reviews</div>
                ) : null}
                {snap.reviews_data.rating ? <div>Rating: {snap.reviews_data.rating}/5</div> : null}
                {snap.reviews_data.source ? <div>Source: {snap.reviews_data.source}</div> : null}
              </div>
            </div>
          </div>

          {snap.sources.length > 0 ? (
            <div className="mt-4 flex flex-wrap gap-2">
              {snap.sources.map((s, i) => (
                <a
                  key={i}
                  href={s.url}
                  target="_blank"
                  rel="noopener noreferrer"
                  className="inline-flex items-center gap-1 rounded-full border bg-card px-2.5 py-1 text-xs text-muted-foreground hover:text-foreground"
                >
                  {s.title} <ExternalLink className="h-3 w-3" />
                </a>
              ))}
            </div>
          ) : null}
        </>
      )}
    </section>
  );
}
