import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import test from "node:test";

const root = new URL("../", import.meta.url);
const read = (path) => readFile(new URL(path, root), "utf8");
const publicOrigin = "https://coderemotemanager.makecdev.com";
const normalizePolicyText = (value) => value.replace(/\s+/g, " ").trim();
const affirmativeAutoRenewClaim = /(?<!does not )(?<!doesn't )(?<!not )(?<!never )(?<!no )\bauto-renews?\b/i;

test("auto-renew contract rejects affirmative claims without rejecting explicit denials", () => {
  for (const claim of ["Pro auto-renews.", "This product auto-renews."]) {
    assert.match(claim, affirmativeAutoRenewClaim);
  }
  for (const disclosure of ["The purchase does not auto-renew.", "It will not auto-renew.", "It never auto-renews."]) {
    assert.doesNotMatch(disclosure, affirmativeAutoRenewClaim);
  }
});

test("installed policy documents describe the developer and app data without an invented account or age limit", async () => {
  const [privacy, terms, storeListing] = await Promise.all([
    read("distribution/PRIVACY.txt"),
    read("distribution/TERMS.txt"),
    read("docs/STORE_LISTING.md"),
  ]);
  const combined = `${privacy}\n${terms}`;

  assert.match(privacy, /^Developer: MakeCdev$/m);
  assert.match(terms, /^Contact: coderemote@makecdev\.com$/m);
  assert.doesNotMatch(terms, /^Developer:/m);
  assert.match(combined, /does not provide its own membership(?:,| or)\s+sign-up account/i);
  assert.match(privacy, /Google ML Kit.*device and app\s+information.*device or installation-scoped\s+identifiers.*performance metrics.*API configuration.*event types.*error codes/is);
  assert.match(privacy, /QR images and results.*on-device.*not sent\s+to Google/is);
  assert.match(privacy, /HTTPS.*not shared with third\s+parties/is);
  assert.match(privacy, /free to download.*one-time non-consumable Pro purchase.*five\s+execution accounts/is);
  assert.match(terms, /free to download.*one execution account.*Pro.*five execution accounts/is);
  assert.match(storeListing, /무료 다운로드.*원격 기능.*실행 계정 1개.*Pro.*계정 5개/s);
  assert.doesNotMatch(combined, /Operator:|at least 18|under 18|minor|children and teenagers|MakeCdev (?:membership )?account/i);
  assert.doesNotMatch(`${combined}\n${storeListing}`, /subscriptions? (?:are|is) (?:available|included)|paid plans? (?:are|is) (?:available|included)/i);
});

test("English terms define the Android Pro purchase without selling Codex access", async () => {
  const terms = await read("distribution/TERMS.txt");
  const normalizedTerms = normalizePolicyText(terms);

  assert.match(normalizedTerms, /free to download.*all remote features.*one (?:execution )?account/is);
  assert.match(normalizedTerms, /Pro.*(?:up to )?five (?:execution )?accounts/is);
  assert.match(normalizedTerms, /`?pro_multi_account`?/i);
  assert.match(normalizedTerms, /one-time non-consumable purchase/i);
  assert.match(normalizedTerms, /Google Play.*billing/i);
  assert.match(normalizedTerms, /restore (?:the )?purchase/i);
  assert.match(normalizedTerms, /cancel(?:lation|ed).*refund.*Pro access/is);
  assert.match(normalizedTerms, /verification service outage.*seven-day grace/is);
  assert.match(normalizedTerms, /certificate.*valid for 30 days.*restore (?:the )?purchase.*reverif/is);
  assert.match(normalizedTerms, /service.*(?:shut down|discontinu).*existing purchasers.*(?:retain Pro|multi-account.*free)/is);
  assert.match(normalizedTerms, /coderemote@makecdev\.com/);
  assert.match(normalizedTerms, /(?:Code Remote Manager|The app) does not (?:provide|require) (?:a |an |its own )?(?:Code Remote )?(?:login|membership|sign-up account)/i);
  assert.doesNotMatch(normalizedTerms, /Codex\s+(?:access|usage|subscription)\s+(?:is|are)\s+(?:included|purchased|sold)|includes?\s+(?:a\s+)?Codex\s+(?:access|usage|subscription)/i);
  assert.doesNotMatch(normalizedTerms, /subscription (?:is|will be) (?:available|included)/i);
  assert.doesNotMatch(normalizedTerms, affirmativeAutoRenewClaim);
  assert.doesNotMatch(normalizedTerms, /automatically reverif|reverif(?:ied|y) every 30 days/i);
});

test("Korean Store Listing defines the same free and Pro account boundary", async () => {
  const storeListing = await read("docs/STORE_LISTING.md");

  assert.match(storeListing, /무료 다운로드.*원격 기능.*계정 1개/s);
  assert.match(storeListing, /Pro.*계정 5개/s);
  assert.match(storeListing, /`pro_multi_account`/);
  assert.match(storeListing, /비소모성.*일회성 구매/s);
  assert.match(storeListing, /Google Play.*결제/s);
  assert.match(storeListing, /구매 복원/);
  assert.match(storeListing, /취소.*환불.*Pro.*(?:종료|회수)/s);
  assert.match(storeListing, /검증 서비스.*장애.*7일.*유예/s);
  assert.match(storeListing, /서비스 종료.*기존 구매자.*(?:Pro.*보존|다계정.*무료)/s);
  assert.match(storeListing, /coderemote@makecdev\.com/);
  assert.match(storeListing, /Code Remote Manager(?:는|에는)[^.\n]{0,120}(?:로그인|회원 계정)[^.\n]{0,80}(?:없|제공하지 않)/);
  assert.match(storeListing, /(?:Policy effective date:\s*2026-08-02|정책 시행일:\s*2026년 8월 2일)/i);
  for (const route of ["privacy", "terms", "support", "delete-account"]) {
    assert.ok(storeListing.includes(`${publicOrigin}/${route}`), route);
  }
  assert.doesNotMatch(storeListing, /구독(?:을 제공합니다|입니다)|구독형 상품(?:입니다|을 제공합니다)|자동 갱신됩니다|Codex (?:사용권|구독)(?:이|은)? (?:포함됩니다|함께 제공됩니다)/);
});

test("privacy notice defines the minimal Pro verification data flow", async () => {
  const privacy = await read("distribution/PRIVACY.txt");
  const normalizedPrivacy = normalizePolicyText(privacy);

  assert.match(normalizedPrivacy, /purchase token.*transient.*verif/is);
  assert.match(normalizedPrivacy, /SHA-256.*purchase token hash/is);
  assert.match(normalizedPrivacy, /installation public-key thumbprint/i);
  assert.match(normalizedPrivacy, /(?:provide|activate).*Pro.*prevent.*(?:fraud|abuse)/is);
  assert.match(normalizedPrivacy, /purchase record.*retain/is);
  for (const processor of ["Google Play", "Cloud Run", "Firestore", "Pub/Sub"]) {
    assert.match(normalizedPrivacy, new RegExp(processor.replace("/", "\\/"), "i"));
  }
  assert.match(normalizedPrivacy, /public purchase-verification route.*validates.*purchase token.*installation binding.*rate-limit/is);
  assert.match(normalizedPrivacy, /internal.*Pub\/Sub.*Scheduler.*OIDC.*authenticated/is);
  assert.doesNotMatch(normalizedPrivacy, /all requests are authenticated/i);
  assert.ok(privacy.includes(`${publicOrigin}/delete-account`));
  assert.ok(privacy.includes(`${publicOrigin}/support`));
  assert.match(normalizedPrivacy, /does not collect (?:Google (?:account )?email(?: addresses?)?[^.]{0,40}(?:payment methods?|payment-method details?)|(?:payment methods?|payment-method details?)[^.]{0,40}Google (?:account )?email(?: addresses?)?)/i);
  assert.match(normalizedPrivacy, /does not (?:retain|store).*raw purchase token/is);
});

test("installed terms and privacy expose the common effective date and public URLs", async () => {
  const [terms, privacy] = await Promise.all([
    read("distribution/TERMS.txt"),
    read("distribution/PRIVACY.txt"),
  ]);

  for (const document of [terms, privacy]) {
    assert.match(document, /^Effective date: August 2, 2026$/m);
    for (const route of ["privacy", "terms", "support", "delete-account"]) {
      assert.ok(document.includes(`${publicOrigin}/${route}`), route);
    }
  }
});

test("Play Data Safety worksheet records implemented processing and requires final artifact confirmation", async () => {
  const worksheet = await read("docs/PLAY_DATA_SAFETY.md");
  const normalized = normalizePolicyText(worksheet);

  assert.match(normalized, /evidence worksheet/i);
  assert.match(normalized, /assessment.*final (?:signed )?(?:AAB|artifact).*Play Console/is);
  assert.match(normalized, /purchase history.*collected.*app functionality.*fraud prevention/is);
  assert.match(normalized, /encrypted in transit.*HTTPS/is);
  assert.match(normalized, /not sold.*no advertising/is);
  assert.match(normalized, /active purchase.*while.*valid.*invalidated.*180 days.*Pub\/Sub.*30 days/is);
  assert.match(normalized, /deletion request.*coderemote@makecdev\.com/is);
  for (const sdk of [
    "Google Play Billing Library 9.1.0",
    "Capacitor Android 8.0.0",
    "Capacitor Barcode Scanner 3.1.0",
    "Google ML Kit barcode scanning 17.3.0",
    "ionbarcode-android 2.1.0",
    "ZXing 3.5.3",
  ]) {
    assert.ok(worksheet.includes(sdk), sdk);
  }
});

test("Pro operations guide maps every public claim to authoritative source and Play Console field", async () => {
  const operations = await read("docs/PRO_ENTITLEMENT_OPERATIONS.md");

  assert.match(operations, /## 공개 문구 동기화 매트릭스/);
  assert.match(operations, /공개 주장 \| 권위 source \| Play Console field/);
  for (const claim of [
    "무료/Pro 계정 한도",
    "일회성 비소모성 구매와 현지 가격",
    "구매 복원",
    "환불과 지원",
    "검증 데이터와 처리자",
    "보존과 삭제",
    "검증 장애와 서비스 종료",
  ]) {
    assert.ok(operations.includes(claim), claim);
  }
  for (const source of [
    "distribution/TERMS.txt",
    "distribution/PRIVACY.txt",
    "docs/STORE_LISTING.md",
    "docs/PLAY_DATA_SAFETY.md",
  ]) {
    assert.ok(operations.includes(source), source);
  }
});

test("installed third-party overview matches the verified Android bundle counts", async () => {
  const [notices, pwaNotices] = await Promise.all([
    read("distribution/THIRD_PARTY_NOTICES.txt"),
    read("apps/pwa/public/legal/PWA-THIRD-PARTY-NOTICES.txt"),
  ]);

  assert.match(notices, /143\s+release runtime dependencies/i);
  assert.match(notices, /seven versioned Capacitor license files/i);
  assert.doesNotMatch(notices, /six versioned Capacitor license files/i);
  assert.match(notices, /interface includes Lucide icons.*ISC/is);
  assert.doesNotMatch(notices, /Lucide AppWindow/i);
  assert.match(notices, /Feather.*MIT/is);
  assert.match(pwaNotices, /lucide-react 1\.25\.0[\s\S]*ISC License/);
  assert.match(pwaNotices, /react [0-9.]+[\s\S]*MIT License/);
  assert.match(pwaNotices, /react-dom [0-9.]+[\s\S]*MIT License/);
});

test("active release documents show the Android one-time Pro target with subscriptions deferred", async () => {
  const [checklist, roadmap, storeListing, design, operations] = await Promise.all([
    read("docs/PRE_RELEASE_CHECKLIST.md"),
    read("ROADMAP.md"),
    read("docs/STORE_LISTING.md"),
    read("docs/superpowers/specs/2026-08-01-android-pro-entitlement-design.md"),
    read("docs/PRO_ENTITLEMENT_OPERATIONS.md"),
  ]);

  assert.match(checklist, /갱신일: 2026-08-03/);
  assert.match(checklist, /Android 서명 RC \| 완료/);
  assert.match(checklist, /Google·Play 내부 스테이징 \+ Windows 다운로드 사이트 준비 \| \*\*현재 작업\*\*/);
  assert.match(checklist, /## 사용자가 결정해야 할 항목/);
  assert.match(checklist, /Billing 9\.1\.0.*Google Auth Library 11\.0\.0.*Firestore Client 8\.7\.0/s);
  assert.match(checklist, /구매 토큰을 네이티브 경계.*무료 1개\/Pro 5개/s);
  assert.match(checklist, /Windows `\.exe` 다운로드.*셀프 설치 설명서.*한국어·영어/s);
  assert.match(checklist, /감사용 AAB.*placeholder.*unsigned.*업로드 후보가 아니다/s);
  assert.match(checklist, /Android Play Billing과 구매·복원 UX 구현 — 완료/);
  assert.doesNotMatch(checklist, /Android 결제 구현이나 검증 서비스 배포는 아직 시작하지 않았다/);
  assert.match(checklist, /구독.*후속 버전.*Android.*iOS StoreKit/s);
  assert.match(checklist, /CRM 구독 계정.*Codex 실행 계정.*분리/s);
  assert.match(checklist, /출시 버전.*versionCode.*재패키징.*서명.*실기기/s);
  assert.doesNotMatch(checklist, /앱 구독 기반 준비 \| \*\*현재 작업\*\*|Android 서명 RC \| \*\*현재 작업\*\*|## 운영자가 결정해야 할 항목|Tailnet은 운영자 계정/);
  assert.match(roadmap, /Android `1\.0\.0` launch.*free download.*non-consumable Google Play purchase.*five configured execution accounts/s);
  assert.match(roadmap, /Subscriptions remain deferred.*CRM identity.*separate.*OpenAI\/Codex execution account/s);
  assert.match(roadmap, /Status as of 2026-08-01/);
  assert.match(design, /Google Play 상품 ID: `pro_multi_account`/);
  assert.match(design, /별도 Code Remote 회원가입 또는 Google 로그인: 없음/);
  assert.match(design, /distribution\/TERMS\.txt.*distribution\/PRIVACY\.txt.*website\/content\.mjs.*docs\/STORE_LISTING\.md/s);
  assert.match(operations, /약관·개인정보·사이트 동기화/);
  assert.match(operations, /공식 정책 확인 링크/);
  assert.match(storeListing, /한 사람이 자신의 장비를 관리하는\s+개인용 도구/);
  assert.doesNotMatch(storeListing, /한 명의 운영자를 위한/);
});

test("current policy patch records conditional Google Play identity disclosures", async () => {
  const checklist = await read("docs/PRE_RELEASE_CHECKLIST.md");

  assert.match(checklist, /개인 개발자 계정.*법적 이름.*법적 주소.*Play Console/s);
  assert.match(checklist, /무료.*인앱 결제.*전체 주소.*공개.*요구되지\s+않/s);
  assert.match(checklist, /대한민국.*개인 개발자.*개발자 전화번호/s);
  assert.match(checklist, /유료 앱.*인앱 결제.*사업자등록번호.*통신판매업/s);
  assert.match(checklist, /공개 개발자명.*MakeCdev.*유지/s);
});

test("current policy patch records the final ML Kit data disclosure scope", async () => {
  const checklist = await read("docs/PRE_RELEASE_CHECKLIST.md");

  assert.match(checklist, /ML Kit.*기기 정보.*앱 정보.*설치별 식별자.*성능 지표.*API 구성.*이벤트.*오류 코드/s);
  assert.match(checklist, /QR 영상.*결과.*기기 내.*Google 서버.*전송하지 않/s);
  assert.match(checklist, /HTTPS.*제3자에게 공유하지 않/s);
});
