// v2-pages.jsx — About, Services, Projects, Contact

const { useState: useP2State } = React;

// ══════════════════════════════════════════════════════════════
// ABOUT
// ══════════════════════════════════════════════════════════════
function AboutPage2({ onContact }) {
  const steps = [
    { n: "01", t: "Vision",     d: "We begin with a deep dive into the project — drawings, 3D models, references and marketing goals. The outcome is a shared vision of the final result, agreed by both sides before a single frame is lit." },
    { n: "02", t: "Atmosphere", d: "Lighting, materials, cameras and mood. We add the small, deliberate details that create atmosphere — these are what make a visualization feel alive rather than rendered." },
    { n: "03", t: "Creation",   d: "Photoreal stills and animation with equal attention to accuracy and artistic expression. Every frame passes several internal quality reviews before it reaches you." },
    { n: "04", t: "Delivery",   d: "Final materials in the formats your campaign needs. The visualization becomes a working tool — it sells, presents and defends the architectural idea." },
  ];
  const tools = [
    { name: "Blender",       role: "Modeling & scene-building" },
    { name: "Cycles",        role: "Offline rendering — painterly light" },
    { name: "Unreal Engine", role: "Real-time, walkthroughs, cinematics" },
    { name: "Substance",     role: "In-house PBR material library" },
    { name: "Generative AI", role: "Moodboards, set dressing, post" },
    { name: "Photoshop",     role: "Compositing & final colour" },
  ];
  return (
    <div className="page2">
      <section className="page-hero" data-screen-label="About — hero">
        <Reveal><IndexLine n="01" tone="dark">The studio</IndexLine></Reveal>
        <Reveal delay={120}>
          <h1 className="d1" style={{ color: "var(--w-1)" }}>
            Precision is a craft.<br /><em>Atmosphere is a choice.</em>
          </h1>
        </Reveal>
        <Reveal delay={240}>
          <p className="page-hero-sub">
            Obsidian Studio is an architectural visualization practice based in
            Lviv, working with architects, designers and developers across Europe.
            Every frame combines documentary accuracy with the mood that makes
            people care about a building that doesn't exist yet.
          </p>
        </Reveal>
      </section>

      <section className="sec dark tight" data-screen-label="About — method">
        <Reveal>
          <div className="sec-head">
            <IndexLine n="02" tone="dark">Method</IndexLine>
            <h2 className="d2" style={{ color: "var(--w-1)" }}>The same path,<br /><em>every time.</em></h2>
          </div>
        </Reveal>
        <ol className="method-list">
          {steps.map((s, i) => (
            <Reveal key={s.n} as="li" delay={i * 70} className="method-row">
              <span className="label" style={{ color: "var(--accent)" }}>{s.n}</span>
              <h3 className="d3">{s.t}</h3>
              <p>{s.d}</p>
            </Reveal>
          ))}
        </ol>
      </section>

      <section className="sec light" data-screen-label="About — toolkit">
        <div className="manif-grid">
          <Reveal>
            <div>
              <IndexLine n="03" tone="light">Toolkit</IndexLine>
              <h2 className="d2" style={{ color: "var(--b-1)", marginTop: "28px" }}>
                Modern tools,<br /><em>classical eyes.</em>
              </h2>
            </div>
          </Reveal>
          <Reveal delay={150}>
            <div className="manif-copy">
              <p className="lead" style={{ color: "var(--b-2)" }}>
                Blender and Cycles for geometry and slow, painterly light.
                Unreal Engine for real-time and film. Generative tools for
                direction and dressing. We choose the instrument that serves
                the brief — never the other way around.
              </p>
              <div className="tool-list">
                {tools.map(t => (
                  <div key={t.name} className="tool-row">
                    <span className="tool-name">{t.name}</span>
                    <span className="tool-role label">{t.role}</span>
                  </div>
                ))}
              </div>
            </div>
          </Reveal>
        </div>
      </section>

      <Closing2 onContact={onContact} />
    </div>
  );
}

// ══════════════════════════════════════════════════════════════
// SERVICES
// ══════════════════════════════════════════════════════════════
const SERVICES2 = [
  {
    key: "residential", label: "Residential", num: "01",
    intro: "Private houses to large complexes — exteriors, interiors and aerials that frame architecture, atmosphere and the life inside it.",
    packs: [
      { name: "Starter Home",        price: "$1,200",  note: "Single house, the essentials.",      items: ["2 exterior stills, daytime", "2–3 interiors — living, kitchen, bedroom", "4K resolution", "1 revision round"] },
      { name: "Apartment Complex",   price: "$4,500",  note: "Mid-scale multi-unit projects.",     items: ["3–4 exteriors incl. aerial", "5–6 interiors — apartments, lobby, corridors", "4K resolution", "2 revision rounds"], featured: true },
      { name: "Premium Residential", price: "$7,000",  note: "A full marketing rollout.",          items: ["6+ exteriors, day & night", "8–10 interiors", "Aerial view", "20–30s flythrough film", "Vertical crops for social"] },
    ],
  },
  {
    key: "commercial", label: "Commercial", num: "02",
    intro: "Offices, retail and mixed-use. Day and evening sets, detailed interiors and aerials that let investors read scale at a glance.",
    packs: [
      { name: "Business Starter", price: "$1,500", note: "Small office or retail unit.",          items: ["2 exterior stills, daytime", "2 interiors — lobby, open space", "4K resolution", "1 revision round"] },
      { name: "Corporate",        price: "$3,500", note: "A full office or retail building.",     items: ["3–4 exteriors, day & night", "4–6 interiors — lobby, open space, meeting, terrace", "4K resolution", "2 revision rounds"], featured: true },
      { name: "Flagship",         price: "$8,000", note: "Mixed-use, headquarters, anchors.",     items: ["6–8 exteriors incl. aerials", "6–8 interiors", "30–40s film", "8K stills on request", "Print-ready CMYK exports"] },
    ],
  },
  {
    key: "hospitality", label: "Hospitality", num: "03",
    intro: "Hotels, restaurants, spas and resorts. Images built to evoke arrival — seasonality, light and the mood a guest pays for.",
    packs: [
      { name: "Boutique Hotel",     price: "$2,000",  note: "Small hotel or restaurant.",         items: ["2 exteriors", "3 interiors — lobby, room, restaurant", "4K resolution", "1 revision round"] },
      { name: "Resort",             price: "$5,000",  note: "Multi-building or destination.",     items: ["3–4 exteriors incl. aerial", "6–8 interiors — rooms, spa, restaurant", "4K resolution", "2 revision rounds"], featured: true },
      { name: "Luxury Hospitality", price: "$12,000", note: "A full brand rollout.",              items: ["6+ exteriors, seasonal variations", "10+ interiors — all key spaces", "1–2 minute narrative film", "8K stills, social crops", "Print-ready exports"] },
    ],
  },
  {
    key: "public", label: "Public & Civic", num: "04",
    intro: "Schools, stadiums, cultural centers and infrastructure — visualized in both everyday and ceremonial scenarios, for juries and communities.",
    packs: [
      { name: "Basic Presentation", price: "$1,500", note: "Competition or first approval.",      items: ["2 exteriors", "2 interiors — hall, entrance", "4K resolution", "1 revision round"] },
      { name: "Community",          price: "$3,500", note: "Mid-scale civic project.",            items: ["3–4 exteriors incl. aerial", "5 interiors", "4K resolution", "2 revision rounds"], featured: true },
      { name: "Impact",             price: "$7,500", note: "Major civic or infrastructure.",      items: ["6+ exteriors, day & night", "8+ interiors", "20–30s film", "8K stills, print-ready exports"] },
    ],
  },
  {
    key: "interactive", label: "Interactive", num: "05",
    intro: "Real-time experiences in Unreal Engine 5. Walk the project, change finishes, turn day to night — on sales floors, in pitches, at trade shows.",
    packs: [
      { name: "Interactive Scene",   price: "from $6,000",  note: "One hero scene, real-time.",   items: ["1 hero scene, interior or exterior", "Lumen + Nanite lighting", "Up to 3 finish variants", "Day / night scenarios", "Standalone Windows / Mac build"] },
      { name: "Interactive Suite",   price: "from $14,000", note: "Full project walkthrough.",    items: ["4–6 scenes, interior + exterior", "Finish / layout / furniture configurator", "Day, night & seasonal scenarios", "Showroom-ready build", "Custom branding & UI"], featured: true },
      { name: "Flagship Experience", price: "on request",   note: "VR, kiosks, white-label.",     items: ["Unlimited scenes & configurator depth", "Meta Quest VR support", "Touchscreen kiosk build", "Web deployment via Pixel Streaming", "Dedicated art direction"] },
    ],
  },
];

function ServicesPage2({ onContact }) {
  const [active, setActive] = useP2State("residential");
  const cat = SERVICES2.find(c => c.key === active);

  return (
    <div className="page2">
      <section className="page-hero" data-screen-label="Services — hero">
        <Reveal><IndexLine n="01" tone="dark">Services</IndexLine></Reveal>
        <Reveal delay={120}>
          <h1 className="d1" style={{ color: "var(--w-1)" }}>
            Five disciplines.<br /><em>One level of finish.</em>
          </h1>
        </Reveal>
        <Reveal delay={240}>
          <p className="page-hero-sub">
            From a single still to a fully interactive walkthrough. Prices below
            are starting points — every quote is scoped to the project's scale
            and revision depth.
          </p>
        </Reveal>
      </section>

      <section className="sec dark tight" data-screen-label="Services — packages">
        <div className="svc-layout">
          <nav className="svc-nav" aria-label="Service categories">
            {SERVICES2.map(c => (
              <button
                key={c.key} type="button"
                className={`svc-nav-item ${active === c.key ? "active" : ""}`}
                onClick={() => setActive(c.key)}
              >
                <span className="label svc-nav-num">{c.num}</span>
                <span className="svc-nav-label">{c.label}</span>
              </button>
            ))}
          </nav>

          <div className="svc-body" key={cat.key}>
            <p className="svc-intro">{cat.intro}</p>
            <div className="svc-packs">
              {cat.packs.map((p, i) => (
                <article key={p.name} className={`svc-pack ${p.featured ? "featured" : ""}`}>
                  <header className="svc-pack-head">
                    <div>
                      <h3 className="d3">{p.name}</h3>
                      <p className="svc-pack-note">{p.note}</p>
                    </div>
                    <div className="svc-pack-price-wrap">
                      {p.featured && <span className="label svc-flag">Most requested</span>}
                      <span className="svc-pack-price">{/^\$/.test(p.price) ? "from " + p.price : p.price}</span>
                    </div>
                  </header>
                  <ul className="svc-pack-items">
                    {p.items.map(it => <li key={it}>{it}</li>)}
                  </ul>
                  <div className="svc-pack-cta">
                    <LineLink tone="dark" onClick={onContact}>Enquire</LineLink>
                  </div>
                </article>
              ))}
            </div>

            <div className="svc-custom">
              <p>
                Animations, VR, large series, NDA and white-label work —
                if the project doesn't fit a package, we'll scope it properly.
              </p>
              <GoldLink onClick={onContact}>Request a custom quote</GoldLink>
            </div>
          </div>
        </div>
      </section>
    </div>
  );
}

// ══════════════════════════════════════════════════════════════
// PROJECTS
// ══════════════════════════════════════════════════════════════
function ProjectsPage2({ onOpenProject }) {
  const cats = ["All", "Residential", "Commercial", "Hospitality", "Public", "Interiors"];
  const [filter, setFilter] = useP2State("All");
  const list = (filter === "All" ? PROJECTS : PROJECTS.filter(p => p.cat === filter));

  return (
    <div className="page2">
      <section className="page-hero" data-screen-label="Work — hero">
        <Reveal><IndexLine n="01" tone="dark">Work</IndexLine></Reveal>
        <Reveal delay={120}>
          <h1 className="d1" style={{ color: "var(--w-1)" }}>
            Built in pixels.<br /><em>Sold in person.</em>
          </h1>
        </Reveal>
        <Reveal delay={200}>
          <p className="ed-standfirst">A working archive of visualization — residential, commercial, hospitality and public, produced end-to-end in-house.</p>
        </Reveal>
        <Reveal delay={240}>
          <div className="proj-filters" role="tablist" aria-label="Filter projects">
            {cats.map(c => (
              <button
                key={c} type="button" role="tab" aria-selected={filter === c}
                className={`proj-filter label ${filter === c ? "active" : ""}`}
                onClick={() => setFilter(c)}
              >{c}</button>
            ))}
          </div>
        </Reveal>
      </section>

      <section className="sec dark tight" data-screen-label="Work — grid">
        <div className="sw-cine">
          {list.map((p, i) => (
            <Reveal key={p.slug}>
              <button type="button" className="sw-cine-item work-card" onClick={() => onOpenProject(p.slug)}>
                <Photo id={p.cover} ratio="21/9" w={2200} video={p.video} alt={p.name} />
                <div className="sw-cine-scrim"></div>
                <div className="sw-cine-cap">
                  <div className="sw-cine-top">
                    <span className="work-num label">{String(i + 1).padStart(2, "0")}</span>
                    <span className="label" style={{ color: "var(--w-2)" }}>{p.services[0].toLowerCase().startsWith(p.cat.toLowerCase()) ? p.cat : `${p.cat} · ${p.services[0]}`}</span>
                    <span className="sw-cine-view label">View project →</span>
                  </div>
                  <span className="sw-cine-title">{p.name}</span>
                  <span className="sw-cine-sub">{p.loc} · {p.year}</span>
                </div>
              </button>
            </Reveal>
          ))}
        </div>
      </section>
    </div>
  );
}

// ══════════════════════════════════════════════════════════════
// CONTACT
// ══════════════════════════════════════════════════════════════
function fileToBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(String(reader.result).split(",")[1] || "");
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

// Vercel's serverless functions hard-cap the whole request body around 4.5MB;
// base64 inflates a file by ~33%, so raw attachments must stay well under that
// to leave room for the rest of the JSON payload. Enforced client-side so an
// oversized file never round-trips to the server just to bounce off that limit
// with an unhelpful platform error.
const MAX_ATTACHMENT_BYTES = 3 * 1024 * 1024;

function ContactPage2() {
  const [name, setName]   = useP2State("");
  const [email, setEmail] = useP2State("");
  const [msg, setMsg]     = useP2State("");
  const [scope, setScope] = useP2State("");
  const [file, setFile]   = useP2State(null);
  const [agree, setAgree] = useP2State(false);
  const [sent, setSent]   = useP2State(false);
  const [sending, setSending] = useP2State(false);
  const [error, setError] = useP2State("");

  const canSubmit = name && email && msg && agree && !sending;
  const scopes = ["Stills", "Film", "Interactive", "Full campaign"];

  const handleSubmit = async (e) => {
    e.preventDefault();
    if (!canSubmit) return;
    if (file && file.size > MAX_ATTACHMENT_BYTES) {
      setError("That file is too large (max 3MB) — please compress it or email it directly to hello@obsidian-studio.io.");
      return;
    }
    setSending(true);
    setError("");
    try {
      const attachment = file ? { filename: file.name, content: await fileToBase64(file) } : null;
      const res = await fetch("/api/contact", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name, email, message: msg, scope, attachment }),
      });
      if (!res.ok) {
        const data = await res.json().catch(() => null);
        throw new Error(data && data.error);
      }
      setSent(true);
    } catch (err) {
      setError(err.message || "Something went wrong — please try again or email us directly at hello@obsidian-studio.io.");
    } finally {
      setSending(false);
    }
  };

  return (
    <div className="page2 contact2" data-screen-label="Contact">
      <aside className="contact2-side">
        <div className="contact2-bg" aria-hidden="true">
          <video src="uploads/Story 9x16 v2.mp4" autoPlay muted loop playsInline></video>
        </div>
        <div>
          <Reveal><IndexLine n="05" tone="dark">Contact</IndexLine></Reveal>
          <Reveal delay={120}>
            <h1 className="d2" style={{ color: "var(--w-1)", marginTop: 28 }}>
              {sent ? <>Thank you.<br /><em>We'll be in touch.</em></> : <>Tell us what<br />you're <em>building.</em></>}
            </h1>
          </Reveal>
          <Reveal delay={240}>
            <p className="page-hero-sub" style={{ marginTop: 28 }}>
              {sent
                ? "Your message has reached the studio. Expect a reply from a real person within 24 hours — usually faster on weekdays."
                : "A drawing, a model, or just an idea — send it over. We reply within 24 hours with thoughts, references and a starting quote."}
            </p>
          </Reveal>
        </div>
        <div className="contact2-details">
          <div>
            <span className="label" style={{ color: "var(--w-3)" }}>Direct</span>
            <a className="contact2-mail" href="mailto:hello@obsidian.studio">hello@obsidian.studio</a>
          </div>
          <div>
            <span className="label" style={{ color: "var(--w-3)" }}>Studio</span>
            <span className="contact2-line">Lviv, Ukraine · UTC+2</span>
          </div>
          <div>
            <span className="label" style={{ color: "var(--w-3)" }}>Prefer a call?</span>
            <a className="contact2-mail" href="mailto:hello@obsidian.studio?subject=Intro%20call%20—%20Obsidian%20Studio&body=Hi%20Obsidian%20Studio,%0D%0A%0D%0AI'd%20like%20to%20book%20a%2015-minute%20intro%20call.%20A%20few%20times%20that%20work%20for%20me:%0D%0A">Book a 15-min intro →</a>
          </div>
        </div>
      </aside>

      <section className="contact2-form-wrap">
        {sent ? (
          <div className="contact2-sent">
            <h2 className="d3" style={{ color: "var(--b-1)" }}>Message received.</h2>
            <p className="lead" style={{ color: "var(--b-2)" }}>
              While you wait, the work archive is one click away.
            </p>
            <LineLink tone="light" onClick={() => { setName(""); setEmail(""); setMsg(""); setScope(""); setFile(null); setAgree(false); setError(""); setSent(false); }}>
              Send another message
            </LineLink>
          </div>
        ) : (
          <form className="contact2-form" onSubmit={handleSubmit}>
            <div className="contact2-row2">
              <Field2 label="Name" value={name} onChange={setName} />
              <Field2 label="Email" value={email} onChange={setEmail} type="email" />
            </div>

            <div>
              <span className="label" style={{ color: "var(--b-3)", display: "block", marginBottom: 18 }}>What do you need?</span>
              <div className="scope-row">
                {scopes.map(s => (
                  <button
                    key={s} type="button"
                    className={`scope-chip label ${scope === s ? "active" : ""}`}
                    onClick={() => setScope(scope === s ? "" : s)}
                  >{s}</button>
                ))}
              </div>
            </div>

            <Field2 label="About the project" value={msg} onChange={setMsg} multiline />

            <div className="attach-row">
              <label className="attach-btn">
                <input
                  type="file" className="attach-input"
                  accept=".pdf,.jpg,.jpeg,.png,.zip,.dwg,.skp,.rvt"
                  onChange={(e) => {
                    const f = e.target.files && e.target.files[0] ? e.target.files[0] : null;
                    if (f && f.size > MAX_ATTACHMENT_BYTES) {
                      setError("That file is too large (max 3MB) — please compress it or email it directly to hello@obsidian-studio.io.");
                      e.target.value = "";
                      return;
                    }
                    setError("");
                    setFile(f);
                  }}
                />
                <svg width="15" height="15" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M8 1v10M4 5l4-4 4 4M2 13h12" stroke="currentColor" strokeWidth="1.2" strokeLinecap="square"/></svg>
                <span className="label" style={{ letterSpacing: ".14em" }}>Attach drawings</span>
              </label>
              {file && (
                <span className="attach-file">
                  {file.name}
                  <button type="button" className="attach-clear" onClick={() => setFile(null)} aria-label="Remove file">×</button>
                </span>
              )}
              <span className="attach-hint">PDF, images, archives — plans, references, briefs (max 3MB)</span>
            </div>

            <Check2 checked={agree} onChange={setAgree}>
              I agree with the <a href="#" onClick={e => e.preventDefault()} style={{ textDecoration: "underline" }}>privacy policy</a>
            </Check2>

            {error && <p style={{ color: "#b3423f", fontSize: 14 }}>{error}</p>}

            <GoldLink type="submit" onLight disabled={!canSubmit}>{sending ? "Sending…" : "Send the brief"}</GoldLink>
          </form>
        )}
      </section>
    </div>
  );
}

Object.assign(window, { AboutPage2, ServicesPage2, ProjectsPage2, ContactPage2 });
