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

const { useState: useP2State, useEffect: useP2Effect } = React;

const CMS_API_URL = "https://cms.obsidian-studio.io";

// ══════════════════════════════════════════════════════════════
// 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
// ══════════════════════════════════════════════════════════════
function ServicesPage2({ onContact }) {
  const [categories, setCategories] = useP2State(null);
  const [active, setActive] = useP2State(null);

  useP2Effect(() => {
    fetch(`${CMS_API_URL}/api/service-categories?limit=100&sort=sortOrder`)
      .then(res => res.json())
      .then(data => {
        const docs = data.docs || [];
        setCategories(docs);
        if (docs.length) setActive(docs[0].key);
      })
      .catch(err => console.error("Failed to load service categories:", err));
  }, []);

  if (!categories) {
    return (
      <div className="page2">
        <section className="page-hero" data-screen-label="Services — hero">
          <Reveal><IndexLine n="01" tone="dark">Services</IndexLine></Reveal>
        </section>
      </div>
    );
  }

  const cat = categories.find(c => c.key === active) || categories[0];

  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>

      {cat && (
      <section className="sec dark tight" data-screen-label="Services — packages">
        <div className="svc-layout">
          <nav className="svc-nav" aria-label="Service categories">
            {categories.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.packages.map((p, i) => (
                <article key={p.id || 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, j) => <li key={j}>{it.value}</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 });
