"use client";

// ============================================================
// Smart Gallery — the tenant's media library, powered by @photo-gallery/sdk embedded
// inside the dashboard shell. The SDK owns the gallery experience (grid, lightbox,
// photo + video editors, map, people, versions, comments, AI); this file owns the
// LynkedUp chrome around it: page head, demo-mode banner, sizing, and failure
// containment so a gallery fault can never take the dashboard down.
//
// Storage + identity come from `@/lib/gallery-api` (be-crm data door when the Shell is
// configured, device-local otherwise). Theming comes from GALLERY_THEME_TOKENS, which
// maps the SDK's tokens onto this dashboard's own CSS variables.
// ============================================================

import { Component, type ErrorInfo, type ReactNode } from "react";
import dynamic from "next/dynamic";
import { Icon } from "./ui";
import { useGalleryFeatures, useGalleryStorage } from "@/lib/gallery-api";

const SmartGalleryMount = dynamic(() => import("./smart-gallery-mount"), {
  ssr: false,
  loading: () => <GalleryPlaceholder label="Loading your library…" />,
});

export function SmartGallery({ theme }: { theme: "dark" | "light" }) {
  const { live } = useGalleryStorage();
  // Whole-view gate. `media.view` with the same permissive fallback the feature toggles use, so a
  // superadmin/owner and the demo always pass, and a member is only blocked if they hold some Media
  // perms but not `media.view`. The sidebar keeps the row visible (see sidebar.tsx §4) — the real
  // gate is here.
  const { canView } = useGalleryFeatures();

  return (
    <div className="view gal">
      {/* Slim header — the big PageHead ate vertical space the gallery needs. The CRM topbar already
          shows the "Smart Gallery" title; this compact row (~40px) just adds context and the icon. */}
      <div className="gal-head">
        <span className="gal-head-ic">
          <Icon name="gallery" size={16} />
        </span>
        <h1 className="gal-head-title">Smart Gallery</h1>
        <span className="gal-head-sub">Every photo and video for your jobs — searchable, editable and shareable.</span>
      </div>

      {!live && (
        <div className="gal-banner">
          <Icon name="info" size={14} />
          <span>Demo mode — stored on this device only. It goes live once the Shell + be-crm are connected.</span>
        </div>
      )}

      {canView ? (
        <div className="gal-shell">
          <GalleryBoundary>
            <SmartGalleryMount theme={theme} />
          </GalleryBoundary>
        </div>
      ) : (
        <div className="gal-shell">
          <div className="gal-placeholder">
            <span className="gal-placeholder-ic">
              <Icon name="lock" size={28} />
            </span>
            <h3>You don&apos;t have access to the gallery</h3>
            <p>Ask a workspace admin to grant you the &ldquo;View Smart Gallery&rdquo; permission.</p>
          </div>
        </div>
      )}
    </div>
  );
}

/* ------------------------------------------------------------------ */

function GalleryPlaceholder({ label }: { label: string }) {
  return (
    <div className="gal-placeholder">
      <span className="gal-placeholder-ic">
        <Icon name="gallery" size={30} />
      </span>
      <p>{label}</p>
    </div>
  );
}

interface BoundaryState {
  error: Error | null;
}

/**
 * The gallery is a large third-party surface with canvas, workers and optional ML models. A render
 * fault inside it must degrade to a message rather than blanking the whole dashboard, so it gets its
 * own error boundary. (Error boundaries still require a class component in React 19.)
 */
class GalleryBoundary extends Component<{ children: ReactNode }, BoundaryState> {
  state: BoundaryState = { error: null };

  static getDerivedStateFromError(error: Error): BoundaryState {
    return { error };
  }

  componentDidCatch(error: Error, info: ErrorInfo): void {
    console.error("[smart-gallery] render failed", error, info.componentStack);
  }

  render(): ReactNode {
    const { error } = this.state;
    if (!error) return this.props.children;
    return (
      <div className="gal-placeholder gal-placeholder-error">
        <span className="gal-placeholder-ic">
          <Icon name="alert" size={30} />
        </span>
        <h3>The gallery could not be displayed</h3>
        <p>{error.message || "An unexpected error occurred."}</p>
        <button className="ds-btn v-outline s-sm" onClick={() => this.setState({ error: null })}>
          <Icon name="refresh" size={14} /> Try again
        </button>
      </div>
    );
  }
}
