/**
 * @license
 * SPDX-License-Identifier: Apache-2.0
 */

import React, { useState } from 'react';
import { createPortal } from 'react-dom';
import { Routes, Route, Navigate, useLocation, useNavigate } from 'react-router-dom';
import {
  AlertTriangle,
  LayoutDashboard,
  Mail,
  Phone,
  Store,
  ShieldCheck,
  ShoppingBag,
  Truck,
  Route as RouteIcon,
  ClipboardList,
  Layers,
  Users,
  TrendingUp,
  Monitor,
  X,
} from 'lucide-react';
import {
  useFiestaTenantLocations,
  useFiestaOrderSummary,
  FIESTA_TENANT_ID,
} from '../services/fiestaQueries';
import { str as fstr, num as fnum, roleName, ymd } from '../services/fiestaApi';
import type { AuthUser } from '../services/auth';
import Header from './Header';
import StoreDetailView from './StoreDetailView';
import StoreCatalogView from './StoreCatalogView';
import DispatchHubView from './DispatchHubView';
import DeliveryReportsView from './DeliveryReportsView';
import StoreQRView from './StoreQRView';
import PosView from './PosView';
import PosConsoleView from './PosConsoleView';
import UserStoreSidebar, { type UserNavItem } from './UserStoreSidebar';
import ComparisonModal from './ComparisonModal';
interface UserStorePageProps {
  /** Returns to the login screen. */
  onLogout: () => void;
  /** The signed-in user, allocated to a single store via their applocationid. */
  user: AuthUser;
}

// Sidebar navigation. Add entries here as new user sections are built — each id
// gets a matching branch in `renderSection` below.
const NAV_ITEMS: UserNavItem[] = [
  { id: 'console', label: 'Store Console', icon: LayoutDashboard },
  { id: 'inventory', label: 'Products', icon: Layers },
  { id: 'customers', label: 'Customers', icon: Users },
  { id: 'dispatch', label: 'Console', icon: RouteIcon },
  { id: 'pos', label: 'POS', icon: Monitor },
  { id: 'reports', label: 'Reports', icon: ClipboardList },
];

type StoreShape = React.ComponentProps<typeof StoreDetailView>['store'];

/**
 * Landing workspace for a non-admin user. A user is allocated to exactly one
 * store (their applocationid), so this resolves that store from the tenant's
 * outlet list and renders the full store console scoped to it — no registry,
 * no other stores. Layout mirrors the admin console (fixed Header + left rail).
 */
export default function UserStorePage({ onLogout, user }: UserStorePageProps) {
  const [sidebarOpen, setSidebarOpen] = useState(false);
  const [showQrModal, setShowQrModal] = useState(false);
  const location = useLocation();
  const navigate = useNavigate();
  
  // Extract the current section from the URL for Header context
  const pathParts = location.pathname.split('/');
  const activeSection = pathParts[pathParts.length - 1] || 'console';

  // Scope every query to the signed-in merchant's tenant; the shared constant is
  // only a fallback for legacy sessions whose record predates tenantid capture.
  const tenantId = user.tenantid || FIESTA_TENANT_ID;

  const todayStr = ymd(new Date());
  const locationsQ = useFiestaTenantLocations(tenantId, user.userid);

  const locations = locationsQ.data ?? [];

  // Resolve the user's store. Most tenants have exactly ONE store, so when the
  // tenant has a single location we just use it — no id matching needed. Only if
  // a tenant has multiple outlets do we disambiguate by the user's applocationid
  // (accepting a row whose locationid equals it too), then by locationid.
  const apploc = user.applocationid;
  const locid = user.locationid;
  const userEmail = user.email?.toLowerCase() || '';

  const matchedLoc =
    locations.length === 1
      ? locations[0]
      : (locations.find((l) => locid != null && locid > 0 && fnum(l.locationid) === locid) ??
         locations.find((l) => {
           // Backend bug fallback: when locationid is 0, we disambiguate using the email prefix
           // e.g. 'abhishek.peelamedu@suriya.com' matches store 'peelamedu@suriya.com'
           const storeEmail = fstr(l.email).toLowerCase();
           if (storeEmail && storeEmail.includes('@')) {
             const prefix = storeEmail.split('@')[0];
             if (prefix.length > 2 && userEmail.includes(prefix)) return true;
           }
           return false;
         }) ??
         locations.find((l) => apploc != null && apploc > 0 && fnum(l.locationid) === apploc) ??
         locations.find((l) => apploc != null && apploc > 0 && fnum(l.applocationid) === apploc) ??
         null);

  // Resolve the locationid the store console queries by. Prefer the matched
  // outlet, then the user's own locationid, then the applocationid as a last
  // resort so the console still scopes to a single store rather than all of them.
  const resolvedLocationId =
    (matchedLoc && fnum(matchedLoc.locationid)) || user.locationid || user.applocationid || 0;

  // The POS reads treat `locationid` as their authorisation boundary, so this
  // deliberately does NOT inherit the fallback chain above: `applocationid` is
  // a city id, not an outlet, and passing one would scope the query to a store
  // that is either empty or — if the ids happen to collide — somebody else's.
  // Only a real tenantlocations.locationid is accepted; otherwise the POS page
  // says so rather than showing another shop's takings.
  const posLocationId = (matchedLoc && fnum(matchedLoc.locationid)) || 0;

  const orderSummaryQ = useFiestaOrderSummary(tenantId, todayStr, todayStr, resolvedLocationId || undefined);
  const sum = orderSummaryQ.data;

  const storeName =
    (matchedLoc && fstr(matchedLoc.locationname)) ||
    user.applocation ||
    user.locationname ||
    (resolvedLocationId ? `Store ${resolvedLocationId}` : 'Your Store');

  const profile = {
    name: user.name,
    role: user.roleid ? roleName(user.roleid) : 'Team Member',
    email: user.email,
  };

  const initials =
    user.name
      .split(' ')
      .map((w) => w[0])
      .filter(Boolean)
      .slice(0, 2)
      .join('')
      .toUpperCase() || 'NA';

  const handleHelp = () =>
    alert('nearledaily Store User Help — contact your store administrator for access or data questions.');

  // Build the store shape StoreDetailView expects, mirroring the App registry
  // mapping so the console renders identically to the admin's store view.
  const buildStore = (): StoreShape => {
    const status = matchedLoc ? fstr(matchedLoc.status) || 'Active' : 'Active';
    return {
      locationid: resolvedLocationId,
      name: storeName,
      zone: matchedLoc
        ? [fstr(matchedLoc.suburb), fstr(matchedLoc.city)].filter(Boolean).join(', ') || 'Coimbatore'
        : 'Coimbatore',
      deliveries: sum?.delivered ?? 0,
      sales: `${(sum?.total ?? 0).toLocaleString('en-IN')} orders`,
      orders: Math.max(sum?.delivered ?? 0, sum?.total ?? 0),
      staff: (matchedLoc && (fstr(matchedLoc.contactno) || fstr(matchedLoc.email))) || user.name || '—',
      color: status.toLowerCase() === 'active' ? 'emerald' : 'amber',
      status,
    };
  };

  // ── My Account: read-only profile + store binding ──────────────────────────
  const renderAccount = () => (
    <div className="max-w-2xl animate-in fade-in duration-300">
      <h1 className="font-sans font-bold text-2xl tracking-tight text-[#0f172a] mb-1">My Account</h1>
      <p className="text-zinc-500 font-sans text-xs mb-6">Your profile and the store you’re assigned to.</p>

      <div className="bg-white border border-slate-200/70 shadow-sm overflow-hidden">
        <div className="bg-gradient-to-br from-[#662582] via-purple-800 to-purple-950 p-6 text-white flex items-center gap-4">
          <span className="w-14 h-14 rounded-full bg-white/15 ring-2 ring-white/30 flex items-center justify-center text-lg font-bold tracking-wide">
            {initials}
          </span>
          <div className="min-w-0">
            <p className="font-bold text-lg truncate">{user.name}</p>
            <span className="inline-flex items-center gap-1.5 mt-1 text-[10px] font-bold uppercase tracking-wider text-purple-100 bg-white/15 border border-white/20 px-2 py-0.5 rounded-full">
              <ShieldCheck size={11} /> {profile.role}
            </span>
          </div>
        </div>

        <dl className="p-6 divide-y divide-slate-100 text-sm">
          <div className="flex items-center gap-3 py-3">
            <Mail size={15} className="text-slate-400 shrink-0" />
            <dt className="w-32 text-xs font-bold text-slate-400 uppercase tracking-wider">Email</dt>
            <dd className="text-slate-700 font-medium break-all">{user.email || '—'}</dd>
          </div>
          <div className="flex items-center gap-3 py-3">
            <Phone size={15} className="text-slate-400 shrink-0" />
            <dt className="w-32 text-xs font-bold text-slate-400 uppercase tracking-wider">Phone</dt>
            <dd className="text-slate-700 font-medium">{user.contactno || '—'}</dd>
          </div>
          <div className="flex items-center gap-3 py-3">
            <Store size={15} className="text-slate-400 shrink-0" />
            <dt className="w-32 text-xs font-bold text-slate-400 uppercase tracking-wider">App Location</dt>
            <dd className="text-slate-700 font-medium">{user.applocation || storeName || '—'}</dd>
          </div>
          <div className="flex items-center gap-3 py-3">
            <ShieldCheck size={15} className="text-slate-400 shrink-0" />
            <dt className="w-32 text-xs font-bold text-slate-400 uppercase tracking-wider">App Location ID</dt>
            <dd className="text-slate-700 font-medium font-mono">{user.applocationid ?? '—'}</dd>
          </div>
        </dl>
      </div>
    </div>
  );

  // Render the active section. New sidebar items add a branch here; the default
  // keeps anything not-yet-built from breaking the page.
  const renderSection = () => {
    if (activeSection === 'account') return renderAccount();

    // Distinguish a real load failure from "no store assigned" — otherwise an
    // API outage would wrongly tell the user to contact their admin.
    if (locationsQ.isError || orderSummaryQ.isError) {
      return (
        <div className="flex items-center justify-center py-16">
          <div className="bg-white border border-slate-200/70 p-10 text-center max-w-md shadow-[0_10px_40px_rgba(0,0,0,0.08)]">
            <div className="mx-auto h-16 w-16 rounded-2xl bg-rose-50 text-rose-600 ring-1 ring-rose-100 flex items-center justify-center mb-6">
              <AlertTriangle size={30} />
            </div>
            <h1 className="text-2xl font-bold text-slate-900 tracking-tight mb-3">Couldn’t load your store</h1>
            <p className="text-[15px] text-slate-500 leading-relaxed mb-6">
              We couldn’t reach the store service. Check your connection and try again.
            </p>
            <button
              onClick={() => {
                locationsQ.refetch();
                orderSummaryQ.refetch();
              }}
              className="px-5 py-2.5 bg-[#662582] hover:bg-purple-800 text-white text-sm font-bold rounded-xl cursor-pointer transition-colors shadow-sm"
            >
              Retry
            </button>
          </div>
        </div>
      );
    }

    if (!resolvedLocationId) {
      return (
        <div className="flex items-center justify-center py-16">
          <div className="bg-white border border-slate-200/70 p-10 text-center max-w-md shadow-[0_10px_40px_rgba(0,0,0,0.08)]">
            <div className="mx-auto h-16 w-16 rounded-2xl bg-amber-50 text-amber-600 ring-1 ring-amber-100 flex items-center justify-center mb-6">
              <AlertTriangle size={30} />
            </div>
            <h1 className="text-2xl font-bold text-slate-900 tracking-tight mb-3">No store assigned</h1>
            <p className="text-[15px] text-slate-500 leading-relaxed">
              Your account isn’t linked to a store yet. Please contact your administrator to be
              allocated to a store location.
            </p>
          </div>
        </div>
      );
    }

    // Logistics console — scoped to this user's store. These views own their
    // loading/error states, so they don't need the store-console load gating below.
    if (activeSection === 'pos')
      return <PosStoreSection locationid={posLocationId} tenantId={tenantId} storeName={storeName} />;
    if (activeSection === 'pos-till')
      return <PosView locationid={resolvedLocationId || undefined} tenantId={tenantId} />;
    if (activeSection === 'dispatch') return <DispatchHubView locationid={resolvedLocationId || undefined} tenantId={tenantId} />;
    if (activeSection === 'reports') return <DeliveryReportsView tenantId={tenantId} locationid={resolvedLocationId || undefined} />;
    // Inventory & Catalog is its own page: the manager-curated catalog the user
    // stocks from (the catalog query is tenant-level, so it doesn't need the store
    // gating below — only "My Store Inventory" uses the resolved location id).
    if (activeSection === 'inventory') return <StoreCatalogView locationid={resolvedLocationId || undefined} storeName={storeName} tenantId={tenantId} isSidebarOpen={sidebarOpen} />;

    // The store console needs a resolved store, so gate it on the load state.
    if (locationsQ.isLoading || orderSummaryQ.isLoading) {
      return (
        <div className="flex flex-col items-center justify-center gap-3 py-24">
          <div className="w-7 h-7 border-2 border-[#662582] border-t-transparent rounded-full animate-spin" />
          <span className="text-xs font-semibold text-slate-500">Loading your store…</span>
        </div>
      );
    }

    // canManage=false hides write actions in the console. NOTE: this is a UI-only
    // restriction — the backend must also enforce role-based authorization on the
    // write endpoints, since a hidden button doesn't stop a direct API call.
    //
    // The store console is split into separate pages: the "console" nav shows only
    // Overview & Performance; Customers is its own page (Inventory & Catalog is the
    // dedicated StoreCatalogView, handled above).
    const only = activeSection === 'customers' ? 'customers' : 'overview';
    return <StoreDetailView store={buildStore()} canManage={false} only={only} tenantId={tenantId} />;
  };
  const isInactive = matchedLoc && fstr(matchedLoc.status).toLowerCase() !== 'active';

  return (
    <div className="min-h-screen bg-[#f8fafc] text-[#0f172a] font-sans antialiased overflow-x-hidden">
      <Header
        isSidebarOpen={sidebarOpen}
        onToggleSidebar={() => setSidebarOpen((s) => !s)}
        onHelpClick={handleHelp}
        onLogoutClick={onLogout}
        onAccountClick={() => navigate('/store/account')}
        onQrClick={() => setShowQrModal(true)}
        profile={profile}
        storeContext={{
          storeName: activeSection === 'console'
            ? storeName
            : activeSection === 'inventory'
              ? 'Products'
              : activeSection === 'pos'
                ? 'POS'
              : activeSection === 'pos-till'
                ? 'POS Terminal'
              : activeSection === 'account'
                ? 'My Account'
              : activeSection === 'dispatch'
                ? 'Console'
                : activeSection.charAt(0).toUpperCase() + activeSection.slice(1),
          icon: activeSection === 'console'
            ? LayoutDashboard
            : activeSection === 'inventory'
              ? Layers
              : activeSection === 'pos'
                ? Monitor
              : activeSection === 'pos-till'
                ? ShoppingBag
              : activeSection === 'customers'
                ? Users
                : activeSection === 'dispatch'
                  ? RouteIcon
                  : activeSection === 'reports'
                    ? ClipboardList
                    : undefined
        }}
      />

      <div className="flex pt-16 w-full max-w-[100vw]">
        <UserStoreSidebar
          items={NAV_ITEMS}
          isOpen={sidebarOpen}
          onClose={() => setSidebarOpen(false)}
        />

        <main
          className={`relative flex-1 min-w-0 transition-all duration-300 ${
            isInactive || activeSection === 'dispatch' || activeSection === 'pos-till' ? 'h-[calc(100vh-64px)] overflow-hidden' : 'min-h-[calc(100vh-64px)]'
          } ${sidebarOpen ? 'md:pl-64' : 'md:pl-16'}`}
        >
          {isInactive && (
            <div className="absolute inset-0 z-50 bg-slate-100/60 backdrop-blur-[2px] flex items-center justify-center">
              <div className="bg-white p-8 shadow-xl text-center w-full min-w-[320px] max-w-sm mx-4 border border-red-100 pointer-events-auto">
                <div className="w-16 h-16 bg-red-100 text-red-600 rounded-full flex items-center justify-center mx-auto mb-4">
                  <Store size={32} />
                </div>
                <h2 className="text-xl font-bold text-slate-800 mb-2">Store is Inactive</h2>
                <p className="text-slate-500 mb-6">This location has been marked as inactive. Operations are disabled.</p>
              </div>
            </div>
          )}
          <Routes>
            <Route index element={<Navigate to="console" replace />} />
            <Route path="account" element={
              <div className="w-full p-container-margin md:p-xl space-y-lg transition-all duration-300">
                {renderAccount()}
              </div>
            } />
            {/* Counter sales and till health for this user's own store. */}
            <Route path="pos" element={
              <div className={`w-full p-container-margin md:p-xl transition-all duration-300 ${isInactive ? 'pointer-events-none opacity-50' : ''}`}>
                <PosStoreSection locationid={posLocationId} tenantId={tenantId} storeName={storeName} />
              </div>
            } />
            {/* The on-screen till itself. Kept at its own path — it is a
                checkout surface, not a reporting one, and shares nothing with
                the POS console above. */}
            <Route path="pos-till" element={
              <div className={`w-full h-full ${isInactive ? 'pointer-events-none opacity-50' : ''}`}>
                <PosView locationid={resolvedLocationId || undefined} tenantId={tenantId} />
              </div>
            } />
            <Route path="dispatch" element={
              <div className={`w-full h-full ${isInactive ? 'pointer-events-none opacity-50' : ''}`}>
                <DispatchHubView locationid={resolvedLocationId || undefined} tenantId={tenantId} />
              </div>
            } />
            <Route path="reports" element={
              <div className={`w-full p-container-margin md:p-xl space-y-lg transition-all duration-300 ${isInactive ? 'pointer-events-none opacity-50' : ''}`}>
                <DeliveryReportsView tenantId={tenantId} locationid={resolvedLocationId || undefined} />
              </div>
            } />
            <Route path="inventory" element={
              <div className={`w-full p-container-margin md:p-xl space-y-lg transition-all duration-300 ${isInactive ? 'pointer-events-none opacity-50' : ''}`}>
                <StoreCatalogView locationid={resolvedLocationId || undefined} storeName={storeName} tenantId={tenantId} />
              </div>
            } />
            <Route path="console" element={
              <div className={`w-full p-container-margin md:p-xl space-y-lg transition-all duration-300 ${isInactive ? 'pointer-events-none opacity-50' : ''}`}>
                <StoreDetailView store={buildStore()} canManage={false} only="overview" tenantId={tenantId} />
              </div>
            } />
            <Route path="customers" element={
              <div className={`w-full p-container-margin md:p-xl space-y-lg transition-all duration-300 ${isInactive ? 'pointer-events-none opacity-50' : ''}`}>
                <StoreDetailView store={buildStore()} canManage={false} only="customers" tenantId={tenantId} />
              </div>
            } />
          </Routes>
        </main>
      </div>

      {/* Store QR — centered modal opened from the navbar QR button. Portaled to
          body so `fixed inset-0` is viewport-relative regardless of ancestors. */}
      {showQrModal &&
        createPortal(
          <div
            className="fixed inset-0 z-[200] flex items-center justify-center p-4"
            style={{ background: 'rgba(15,23,42,0.45)', backdropFilter: 'blur(4px)' }}
            onClick={(e) => { if (e.target === e.currentTarget) setShowQrModal(false); }}
          >
            <div className="relative w-full mx-auto" style={{ maxWidth: 600 }}>
              <button
                onClick={() => setShowQrModal(false)}
                title="Close"
                aria-label="Close"
                className="absolute top-3 right-3 z-10 p-1.5 rounded-full bg-white/15 hover:bg-white/25 text-white ring-1 ring-white/25 backdrop-blur-sm cursor-pointer transition-colors"
              >
                <X size={16} />
              </button>
              <StoreQRView
                tenantId={tenantId}
                locationid={resolvedLocationId || undefined}
                storeName={storeName}
                storeZone={
                  matchedLoc
                    ? [fstr(matchedLoc.suburb), fstr(matchedLoc.city)].filter(Boolean).join(', ') || undefined
                    : undefined
                }
                storeAddress={matchedLoc ? fstr(matchedLoc.address) || undefined : undefined}
              />
            </div>
          </div>,
          document.body,
        )}
        
      <ComparisonModal />
    </div>
  );
}

/**
 * The store-scoped POS console, behind a strict location gate.
 *
 * Kept as its own component so the unresolved-outlet case has somewhere honest
 * to live. Every POS read is authorised by `locationid` alone, so a page that
 * guessed one — from an applocationid, say — would not fail loudly; it would
 * quietly show the wrong shop's takings, or an empty board that looks like a
 * quiet day. Refusing to render is the safe answer.
 */
function PosStoreSection({
  locationid,
  tenantId,
  storeName,
}: {
  locationid: number;
  tenantId: number;
  storeName: string;
}) {
  if (!locationid) {
    return (
      <div className="flex items-center justify-center py-16">
        <div className="bg-white border border-slate-200/70 p-10 text-center max-w-md shadow-[0_10px_40px_rgba(0,0,0,0.08)]">
          <div className="mx-auto h-16 w-16 rounded-2xl bg-amber-50 text-amber-600 ring-1 ring-amber-100 flex items-center justify-center mb-6">
            <AlertTriangle size={30} />
          </div>
          <h1 className="text-2xl font-bold text-slate-900 tracking-tight mb-3">No outlet resolved</h1>
          <p className="text-[15px] text-slate-500 leading-relaxed">
            Counter sales are scoped to a single outlet, and your account isn’t linked to one yet.
            Ask your administrator to allocate you to a store location.
          </p>
        </div>
      </div>
    );
  }

  return <PosConsoleView tenantId={tenantId} locationid={locationid} storeName={storeName} />;
}
