// Full onboarding review. Documents stay private and use short-lived API-signed URLs.
const APPLICATION_LABELS = {
  submitted: 'Awaiting review', changes_requested: 'Changes requested', approved: 'Approved', rejected: 'Rejected',
  business_registration: 'Business registration', insurance_certificate: 'Insurance certificate', warranty_authorization: 'Warranty authorization', other: 'Other document',
  mechanical_repair: 'Mechanical repair', electrical_and_electronic_service: 'Electrical and electronic service', bodywork_and_paint: 'Bodywork and paint', tire_and_wheel_service: 'Tire and wheel service', detailing_and_car_wash: 'Detailing and car wash',
  mechanics: 'Mechanics', diagnostics: 'Diagnostics', tires: 'Tires', brakes: 'Brakes', suspension: 'Suspension', electrical: 'Electrical', bodywork: 'Bodywork', paint: 'Paint', pdr: 'Paintless dent removal', detailing: 'Detailing', car_wash: 'Car wash', towing: 'Towing', roadside_assistance: 'Roadside assistance', pickup_delivery: 'Pickup and delivery',
  manager: 'Manager', mechanic: 'Mechanic', painter: 'Painter', electrician: 'Electrician', owner: 'Owner', staff: 'Staff access', admin: 'Administrator access', general: 'General',
  in_shop: 'At the workshop', mobile: 'Mobile service', instant: 'Instant booking', assessment: 'After assessment', request: 'By request', fixed: 'Fixed price', from: 'Starting price',
  inspection: 'Vehicle inspection', vehicle_sourcing: 'Vehicle sourcing', damage_assessment: 'Damage assessment', management: 'Management', reception: 'Reception',
};
function applicationLabel(value) {
  return tx(APPLICATION_LABELS[value] || String(value || '').replace(/_/g, ' ').replace(/^./, (c) => c.toUpperCase()));
}
function ApplicationStatus({ status }) {
  return <Badge kind={status === 'approved' ? 'success' : status === 'rejected' ? 'danger' : 'warning'} pip>{applicationLabel(status)}</Badge>;
}
function ApplicationField({ label, children }) {
  return <div className="application-field"><dt>{tx(label)}</dt><dd>{children == null || children === '' ? tx('Not provided') : children}</dd></div>;
}
function ApplicationTags({ values }) {
  return values?.length ? <div className="application-tags">{values.map((v) => <Badge key={v}>{applicationLabel(v)}</Badge>)}</div> : tx('Not provided');
}
function ApplicationError({ message, retry }) {
  return <div className="banner-warn application-error" role="alert"><span>{message}</span>{retry && <button type="button" className="btn btn-outline sm" onClick={retry}>{tx('Retry')}</button>}</div>;
}

function ApplicationsView({ applications, go }) {
  const pending = applications.filter((item) => ['submitted', 'changes_requested'].includes(item.status));
  return <div className="page view-fade applications-page">
    <div className="page-head"><div><div className="page-title">{tx('Workshop applications')}</div><div className="page-sub">{tx('Open an application to check its details and documents before approval')}</div></div><span className="spacer" /><Badge kind="warning" pip>{fmt('Awaiting review: {count}', { count: pending.length })}</Badge></div>
    <div className="card applications-card"><table className="tbl applications-table">
      <thead><tr><th scope="col">{tx('Workshop')}</th><th scope="col">{tx('Owner')}</th><th scope="col">{tx('Request')}</th><th scope="col">{tx('Status')}</th><th scope="col"><span className="admin-sr-only">{tx('Actions')}</span></th></tr></thead>
      <tbody>{applications.map((item) => <tr key={item.id} onClick={(event) => { if (!event.target.closest('button, a') && !window.getSelection()?.toString()) go('application', { id: item.id }); }}>
        <td data-label={tx('Workshop')}><button className="application-name" onClick={() => go('application', { id: item.id })}>{item.workshopName}</button><div className="tiny muted">{item.address} · {item.city}</div></td>
        <td data-label={tx('Owner')}><div>{item.ownerName}</div><div className="tiny muted">{item.ownerEmail || item.ownerPhone}</div></td>
        <td data-label={tx('Request')}><Badge>{tx(item.claimTenantId ? 'Ownership claim' : 'New workshop')}</Badge><div className="tiny muted" style={{ marginTop: 5 }}>{fmt('Team members: {count}', { count: (item.team || []).length })}</div></td>
        <td data-label={tx('Status')}><ApplicationStatus status={item.status} /></td>
        <td><button className="btn btn-outline sm" aria-label={fmt('View application: {name}', { name: item.workshopName })} onClick={() => go('application', { id: item.id })}>{tx('View details')}</button></td>
      </tr>)}</tbody>
    </table>{applications.length === 0 && <div className="card-pad muted">{tx('No workshop applications')}</div>}</div>
  </div>;
}

function ApplicationDocument({ applicationId, document: doc }) {
  const [url, setUrl] = React.useState('');
  const [busy, setBusy] = React.useState(true);
  const [error, setError] = React.useState('');
  const [attempt, setAttempt] = React.useState(0);
  React.useEffect(() => {
    const controller = new AbortController();
    setBusy(true); setError(''); setUrl('');
    api(`/platform/tenant-applications/${encodeURIComponent(applicationId)}/documents/${encodeURIComponent(doc.id)}/download-url`, { signal: controller.signal })
      .then((result) => {
        const signed = new URL(result.downloadUrl);
        if (signed.protocol !== 'https:' && !(ADMIN_LOCAL_HOST && signed.protocol === 'http:' && ['localhost', '127.0.0.1'].includes(signed.hostname))) throw new Error('Invalid document URL');
        if (!controller.signal.aborted) setUrl(signed.href);
      })
      .catch(() => { if (!controller.signal.aborted) setError(tx('Could not load the document. Try again to refresh its secure link.')); })
      .finally(() => { if (!controller.signal.aborted) setBusy(false); });
    return () => controller.abort();
  }, [applicationId, doc.id, attempt]);
  const image = ['image/jpeg', 'image/png', 'image/webp'].includes(doc.contentType);
  return <article className="card application-document">
    <div className="application-document-preview">
      {busy ? <p role="status">{tx('Loading document...')}</p> : error ? <ApplicationError message={error} retry={() => setAttempt((n) => n + 1)} /> : image ?
        <a href={url} target="_blank" rel="noopener noreferrer" aria-label={fmt('Open document: {name}', { name: doc.fileName })}><img src={url} alt={doc.fileName} referrerPolicy="no-referrer" onError={() => setError(tx('Could not load the document. Try again to refresh its secure link.'))} /></a> :
        <div className="application-document-file"><b>{doc.contentType === 'application/pdf' ? 'PDF' : tx('Document')}</b><span>{tx('Open the original file to review it')}</span></div>}
    </div>
    <div className="card-pad"><h3>{applicationLabel(doc.kind)}</h3><div className="application-file-name">{doc.fileName}</div><p className="tiny muted">{Number.isFinite(doc.sizeBytes) ? `${(doc.sizeBytes / 1024).toLocaleString(i18nLocale(), { maximumFractionDigits: 1 })} KB · ` : ''}{displayDate(doc.createdAt)}</p>
      {url && !error && <a className="btn btn-outline" href={url} target="_blank" rel="noopener noreferrer">{tx('Open original')}</a>}
      {!busy && !error && <button type="button" className="btn btn-ghost sm" onClick={() => setAttempt((n) => n + 1)}>{tx('Refresh secure link')}</button>}
    </div>
  </article>;
}

function ApplicationDetailView({ applicationId, actions, go }) {
  const [application, setApplication] = React.useState(null);
  const [documents, setDocuments] = React.useState(null);
  const [catalog, setCatalog] = React.useState(null);
  const [errors, setErrors] = React.useState({});
  const [loading, setLoading] = React.useState(true);
  const [attempt, setAttempt] = React.useState(0);
  const [tab, setTab] = React.useState('details');
  const [reviewNote, setReviewNote] = React.useState('');
  const [decision, setDecision] = React.useState('');
  const [reviewBusy, setReviewBusy] = React.useState(false);
  const [reviewError, setReviewError] = React.useState('');
  const decisionRef = React.useRef(null);
  React.useEffect(() => {
    const controller = new AbortController();
    const path = `/platform/tenant-applications/${encodeURIComponent(applicationId)}`;
    setLoading(true); setErrors({}); setDecision('');
    Promise.allSettled([api(path, { signal: controller.signal }), api(`${path}/documents`, { signal: controller.signal }), api('/service-catalog/services', { signal: controller.signal })]).then(([detail, docs, services]) => {
      if (controller.signal.aborted) return;
      const nextErrors = {};
      if (detail.status === 'fulfilled') { setApplication(detail.value); setReviewNote(detail.value.reviewNote || ''); }
      else { setApplication(null); nextErrors.detail = tx('Could not load the application'); }
      if (docs.status === 'fulfilled' && Array.isArray(docs.value)) setDocuments(docs.value);
      else { setDocuments(null); nextErrors.documents = tx('Could not load the documents. Approval is unavailable until they are loaded.'); }
      if (services.status === 'fulfilled') setCatalog(services.value);
      else { setCatalog(null); nextErrors.catalog = tx('Could not load service names. Catalog IDs are shown instead.'); }
      setErrors(nextErrors); setLoading(false);
    });
    return () => controller.abort();
  }, [applicationId, attempt]);
  React.useEffect(() => { if (decision) decisionRef.current?.focus(); }, [decision]);
  const retry = () => setAttempt((n) => n + 1);
  const review = async () => {
    if (reviewBusy || !decision) return;
    if (decision !== 'approved' && !reviewNote.trim()) { setReviewError(tx('Add a reason or describe the required changes')); return; }
    setReviewBusy(true); setReviewError('');
    try {
      const updated = await actions.reviewApplication(application, decision, reviewNote.trim());
      setApplication(updated); setDecision(''); setReviewNote(updated.reviewNote || '');
    } catch (err) { setReviewError(err.message || tx('Could not review application')); }
    finally { setReviewBusy(false); }
  };
  const back = <button className="btn btn-ghost application-back" onClick={() => go('applications')}>{tx('Back to applications')}</button>;
  if (loading) return <div className="page">{back}<div className="card card-pad" role="status">{tx('Loading application...')}</div></div>;
  if (!application) return <div className="page">{back}<ApplicationError message={errors.detail || tx('Application not found')} retry={retry} /></div>;
  const app = application;
  const pending = ['submitted', 'changes_requested'].includes(app.status);
  const tabs = [
    ['details', 'Application details', null], ['documents', 'Documents', documents?.length], ['team', 'Employees', app.team?.length || 0], ['services', 'Services', app.services?.length || 0], ['hours', 'Opening hours', null],
  ];
  const categories = (catalog?.groups || []).flatMap((group) => group.categories || []);
  const weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
  const location = app.location;
  const hasLocation = Number.isFinite(location?.lat) && Number.isFinite(location?.lng);
  const mapUrl = `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(hasLocation ? `${location.lat},${location.lng}` : `${app.address}, ${app.city}`)}${app.googlePlaceId ? `&query_place_id=${encodeURIComponent(app.googlePlaceId)}` : ''}`;
  return <div className="page view-fade application-detail-page">
    {back}
    <div className="page-head"><div><div className="tiny muted">{tx(app.claimTenantId ? 'Ownership claim' : 'New workshop')}</div><h1 className="page-title">{app.workshopName}</h1><div className="page-sub">{app.address} · {app.city}</div></div><span className="spacer" /><ApplicationStatus status={app.status} /></div>
    <div className="application-summary"><span>{tx('Submitted')}: {displayDate(app.submittedAt)}</span><span>{tx('Updated')}: {displayDate(app.updatedAt)}</span><span>{tx('Application ID')}: {app.id}</span></div>
    <div className="application-tabs" role="tablist" aria-label={tx('Application sections')}>
      {tabs.map(([id, label, count], index) => <button key={id} id={`application-tab-${id}`} role="tab" aria-selected={tab === id} aria-controls={`application-panel-${id}`} tabIndex={tab === id ? 0 : -1} onClick={() => setTab(id)} onKeyDown={(event) => {
        let next;
        if (event.key === 'ArrowRight') next = (index + 1) % tabs.length;
        if (event.key === 'ArrowLeft') next = (index + tabs.length - 1) % tabs.length;
        if (event.key === 'Home') next = 0;
        if (event.key === 'End') next = tabs.length - 1;
        if (next != null) { event.preventDefault(); setTab(tabs[next][0]); document.getElementById(`application-tab-${tabs[next][0]}`)?.focus(); }
      }}>{tx(label)}{count != null && <span>{count}</span>}</button>)}
    </div>
    <div role="tabpanel" id={`application-panel-${tab}`} aria-labelledby={`application-tab-${tab}`} tabIndex={0} className="application-panel">
      {tab === 'details' && <div className="application-grid">
        <section className="card card-pad"><h2>{tx('Workshop and registration')}</h2><dl className="application-fields">
          <ApplicationField label="Country">{app.countryCode}</ApplicationField><ApplicationField label="Postcode">{app.postalCode}</ApplicationField>
          <ApplicationField label="Workshop">{app.workshopName}</ApplicationField><ApplicationField label="Tax / registration number">{app.businessTaxId}</ApplicationField><ApplicationField label="Address">{app.address}</ApplicationField><ApplicationField label="City">{app.city}</ApplicationField><ApplicationField label="Coordinates">{hasLocation ? `${location.lat}, ${location.lng}` : null}</ApplicationField><ApplicationField label="Google Place ID">{app.googlePlaceId}</ApplicationField><ApplicationField label="Workshop types"><ApplicationTags values={app.workshopType} /></ApplicationField><ApplicationField label="Specializations"><ApplicationTags values={app.specializations} /></ApplicationField>
        </dl><a className="btn btn-outline" href={mapUrl} target="_blank" rel="noopener noreferrer">{tx('View on map')}</a></section>
        <section className="card card-pad"><h2>{tx('Owner and contacts')}</h2><dl className="application-fields">
          <ApplicationField label="Full name">{app.ownerName}</ApplicationField><ApplicationField label="Email">{app.ownerEmail}</ApplicationField><ApplicationField label="Phone">{app.ownerPhone}</ApplicationField>
          <ApplicationField label="Email confirmation">{app.emailVerifiedAt ? new Date(app.emailVerifiedAt).toLocaleString(i18nLocale()) : tx('Not verified')}</ApplicationField>
          <ApplicationField label="Phone confirmation">{app.phoneVerifiedAt ? new Date(app.phoneVerifiedAt).toLocaleString(i18nLocale()) : tx('Not verified')}</ApplicationField>
          <ApplicationField label="Details confirmed">{app.detailsConfirmedAt ? new Date(app.detailsConfirmedAt).toLocaleString(i18nLocale()) : tx('Not confirmed')}</ApplicationField>
          <ApplicationField label="Tenant ID">{app.tenantId || app.claimTenantId}</ApplicationField>
        </dl>{app.tenantId && <button className="btn btn-outline" onClick={() => go('tenant', { id: app.tenantId })}>{tx('Open workshop')}</button>}</section>
        <section className="card card-pad"><h2>{tx('Warranty and insurance')}</h2><dl className="application-fields">
          <ApplicationField label="Warranty">{tx(app.warranty ? 'Yes' : 'No')}</ApplicationField><ApplicationField label="Warranty brands">{app.warrantyBrands?.length ? app.warrantyBrands.join(', ') : null}</ApplicationField><ApplicationField label="Insurance">{tx(app.insurance ? 'Yes' : 'No')}</ApplicationField><ApplicationField label="Insurers">{app.insurers?.length ? app.insurers.join(', ') : null}</ApplicationField>
        </dl></section>
        <section className="card card-pad"><h2>{tx('Registration documents')}</h2>{errors.documents ? <ApplicationError message={errors.documents} retry={retry} /> : <><p className="muted">{documents.length ? fmt('Uploaded documents: {count}', { count: documents.length }) : tx('No documents uploaded')}</p><button className="btn btn-outline" onClick={() => setTab('documents')}>{tx('Review documents')}</button></>}<p className="tiny muted">{tx('Check the uploaded original before approving the workshop.')}</p></section>
      </div>}
      {tab === 'documents' && <><p className="muted">{tx('Documents are private. Secure viewing links expire automatically.')}</p>{errors.documents ? <ApplicationError message={errors.documents} retry={retry} /> : documents.length ? <div className="application-grid">{documents.map((doc) => <ApplicationDocument key={doc.id} applicationId={app.id} document={doc} />)}</div> : <div className="card card-pad">{tx('No documents uploaded')}</div>}</>}
      {tab === 'team' && <><p className="muted">{tx('These are the employee accounts submitted with this application, not the current workshop team.')}</p><div className="application-grid">{(app.team || []).map((member, index) => <section className="card card-pad" key={`${member.email}-${index}`}><h2>{member.name}</h2><dl className="application-fields"><ApplicationField label="Login email">{member.email}</ApplicationField><ApplicationField label="Phone">{member.phone}</ApplicationField><ApplicationField label="Role">{applicationLabel(member.role)}</ApplicationField><ApplicationField label="Specialization">{applicationLabel(member.specialization)}</ApplicationField><ApplicationField label="Access level">{applicationLabel(member.access)}</ApplicationField></dl></section>)}</div>{!app.team?.length && <div className="card card-pad">{tx('No employees submitted')}</div>}</>}
      {tab === 'services' && <>{errors.catalog && <ApplicationError message={errors.catalog} retry={retry} />}<p className="muted">{tx('Prices are in whole workshop currency units. Currency is assigned from the address on approval.')}</p><div className="application-grid">{(app.services || []).map((service, index) => {
        const category = categories.find((c) => String(c.id) === String(service.catalogCategoryId));
        const item = category?.services?.find((s) => String(s.id) === String(service.catalogServiceId));
        return <section className="card card-pad" key={`${service.catalogCategoryId}-${service.catalogServiceId}-${index}`}><h2>{item?.name || fmt('Service #{id}', { id: service.catalogServiceId })}</h2><p className="tiny muted">{category?.name || fmt('Category #{id}', { id: service.catalogCategoryId })}</p><dl className="application-fields"><ApplicationField label="Price">{Number(service.priceAmount).toLocaleString(i18nLocale())} · {applicationLabel(service.pricingType)}</ApplicationField><ApplicationField label="Duration">{fmt('{count} min', { count: service.durationMinutes })}</ApplicationField><ApplicationField label="Service location">{applicationLabel(service.deliveryMode)}</ApplicationField><ApplicationField label="Booking mode">{applicationLabel(service.bookingMode)}</ApplicationField><ApplicationField label="Slot interval">{fmt('{count} min', { count: service.slotIntervalMinutes })}</ApplicationField><ApplicationField label="Enabled">{tx(service.active ? 'Yes' : 'No')}</ApplicationField></dl></section>;
      })}</div>{!app.services?.length && <div className="card card-pad">{tx('No services submitted')}</div>}</>}
      {tab === 'hours' && <><p className="muted">{tx('Time zone')}: {app.timezone || tx('Assigned from the workshop address')}</p><div className="application-grid">{(app.availability || []).map((hour, index) => <section className="card card-pad" key={index}><h2>{tx(weekdays[hour.weekday] || 'Unknown day')}</h2><dl className="application-fields"><ApplicationField label="Opening hours">{hour.opensAt}–{hour.closesAt}</ApplicationField><ApplicationField label="Work type">{applicationLabel(hour.workType)}</ApplicationField><ApplicationField label="Capacity">{hour.capacity}</ApplicationField></dl></section>)}</div>{!app.availability?.length && <div className="card card-pad">{tx('No schedule submitted. The default weekday schedule is applied on approval.')}</div>}</>}
    </div>
    <section className="card card-pad application-review" aria-label={tx('Application decision')}>
      <h2>{tx('Application decision')}</h2>
      {pending ? <>
        {errors.documents && <ApplicationError message={errors.documents} retry={retry} />}
        <label className="field"><span>{tx('Review note')}</span><textarea className="input" rows={3} value={reviewNote} disabled={reviewBusy} onChange={(e) => setReviewNote(e.target.value)} placeholder={tx('Required for rejection or requesting changes')} /></label>
        {reviewError && <ApplicationError message={reviewError} />}
        {decision ? <div className="application-confirm" ref={decisionRef} tabIndex={-1} role="group" aria-label={tx('Confirm decision')}><p>{tx(decision === 'approved' ? 'Approve this application and grant workshop access?' : decision === 'rejected' ? 'Reject this application?' : 'Send this application back for changes?')}</p><div className="application-review-actions"><button className="btn btn-outline" disabled={reviewBusy} onClick={() => setDecision('')}>{tx('Cancel')}</button><button className={`btn ${decision === 'rejected' ? 'btn-danger' : 'btn-primary'}`} disabled={reviewBusy || (decision === 'approved' && documents == null)} onClick={review}>{tx(reviewBusy ? 'Saving...' : 'Confirm decision')}</button></div></div> :
          <div className="application-review-actions"><button className="btn btn-outline" onClick={() => { setReviewError(''); setDecision('changes_requested'); }}>{tx('Request changes')}</button><button className="btn btn-danger" onClick={() => { setReviewError(''); setDecision('rejected'); }}>{tx('Reject')}</button><button className="btn btn-primary" disabled={documents == null} onClick={() => { setReviewError(''); setDecision('approved'); }}>{tx(app.claimTenantId ? 'Approve claim' : 'Approve')}</button></div>}
      </> : <><ApplicationStatus status={app.status} /><p className="application-review-note">{app.reviewNote || tx('No review note')}</p></>}
    </section>
  </div>;
}
