import { describe, it, expect } from 'vitest';
import { readFileSync } from 'node:fs';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import Ajv from 'ajv';
import addFormats from 'ajv-formats';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const schemaPath = resolve(__dirname, '../schemas/brief.schema.json');
const examplePath = resolve(__dirname, '../examples/brief-local-business.json');

const schema = JSON.parse(readFileSync(schemaPath, 'utf-8'));
const example = JSON.parse(readFileSync(examplePath, 'utf-8'));

const ajv = new Ajv({ allErrors: true, strict: false });
addFormats(ajv);
const validate = ajv.compile(schema);

function clone<T>(o: T): T {
  return JSON.parse(JSON.stringify(o));
}

describe('brief schema — baseline', () => {
  it('example brief is valid', () => {
    const valid = validate(example);
    if (!valid) console.error(validate.errors);
    expect(valid).toBe(true);
  });

  it('rejects missing business_name', () => {
    const invalid = clone(example);
    delete (invalid.common as any).business_name;
    expect(validate(invalid)).toBe(false);
  });

  it('rejects invalid language code', () => {
    const invalid = clone(example);
    (invalid.common as any).language = 'ITALIAN';
    expect(validate(invalid)).toBe(false);
  });

  it('rejects brief without contacts field', () => {
    const invalid = clone(example);
    delete (invalid as any).contacts;
    expect(validate(invalid)).toBe(false);
  });

  it('rejects brief with empty contacts object', () => {
    const invalid = clone(example);
    (invalid as any).contacts = {};
    expect(validate(invalid)).toBe(false);
  });

  it('accepts brief with only whatsapp contact (local_business with address)', () => {
    const valid = clone(example);
    (valid as any).contacts = {
      whatsapp: "+39 333 1234567",
      address: "Via Roma 42, Milano",
      city: "Milano",
    };
    (valid.structure as any).primary_cta = "whatsapp";
    (valid.structure as any).sections = ["hero", "contact", "footer"];
    delete (valid as any).services;
    delete (valid as any).hours;
    expect(validate(valid)).toBe(true);
  });
});

describe('brief schema — time format', () => {
  it('rejects invalid hour 25:00', () => {
    const invalid = clone(example);
    (invalid.hours!.schedule[0] as any).open = "25:00";
    expect(validate(invalid)).toBe(false);
  });

  it('rejects invalid minute 12:60', () => {
    const invalid = clone(example);
    (invalid.hours!.schedule[0] as any).close = "12:60";
    expect(validate(invalid)).toBe(false);
  });

  it('accepts edge value 00:00', () => {
    const valid = clone(example);
    (valid.hours!.schedule[0] as any).open = "00:00";
    expect(validate(valid)).toBe(true);
  });

  it('accepts edge value 23:59', () => {
    const valid = clone(example);
    (valid.hours!.schedule[0] as any).close = "23:59";
    expect(validate(valid)).toBe(true);
  });
});

describe('brief schema — sections uniqueness', () => {
  it('rejects duplicate sections', () => {
    const invalid = clone(example);
    (invalid.structure as any).sections = ["hero", "services", "services", "footer"];
    expect(validate(invalid)).toBe(false);
  });

  it('rejects unknown section id', () => {
    const invalid = clone(example);
    (invalid.structure as any).sections = ["hero", "unknown_section"];
    expect(validate(invalid)).toBe(false);
  });
});

describe('brief schema — primary_cta consistency', () => {
  it('rejects primary_cta=phone without phone', () => {
    const invalid = clone(example);
    delete (invalid.contacts as any).phone;
    expect(validate(invalid)).toBe(false);
  });

  it('rejects primary_cta=email without email', () => {
    const invalid = clone(example);
    delete (invalid.contacts as any).email;
    (invalid.structure as any).primary_cta = "email";
    expect(validate(invalid)).toBe(false);
  });

  it('rejects primary_cta=whatsapp without whatsapp', () => {
    const invalid = clone(example);
    (invalid.structure as any).primary_cta = "whatsapp";
    expect(validate(invalid)).toBe(false);
  });

  it('rejects primary_cta=form without form_capture module', () => {
    const invalid = clone(example);
    (invalid.structure as any).primary_cta = "form";
    (invalid as any).functional = { modules: ["cookie_consent"] };
    expect(validate(invalid)).toBe(false);
  });

  it('rejects primary_cta=form without functional field', () => {
    const invalid = clone(example);
    (invalid.structure as any).primary_cta = "form";
    delete (invalid as any).functional;
    expect(validate(invalid)).toBe(false);
  });

  it('accepts primary_cta=form with form_capture module', () => {
    const valid = clone(example);
    (valid.structure as any).primary_cta = "form";
    (valid as any).functional = { modules: ["form_capture"] };
    expect(validate(valid)).toBe(true);
  });
});

describe('brief schema — site_type conditional', () => {
  it('rejects local_business without address', () => {
    const invalid = clone(example);
    delete (invalid.contacts as any).address;
    expect(validate(invalid)).toBe(false);
  });

  it('rejects local_business without city', () => {
    const invalid = clone(example);
    delete (invalid.contacts as any).city;
    expect(validate(invalid)).toBe(false);
  });

  it('accepts personal_brand without address and city', () => {
    const valid = clone(example);
    (valid as any).site_type = "personal_brand";
    delete (valid.contacts as any).address;
    delete (valid.contacts as any).city;
    delete (valid as any).services;
    delete (valid as any).hours;
    (valid.structure as any).sections = ["hero", "about", "contact", "footer"];
    expect(validate(valid)).toBe(true);
  });

  it('accepts agency without address and city', () => {
    const valid = clone(example);
    (valid as any).site_type = "agency";
    delete (valid.contacts as any).address;
    delete (valid.contacts as any).city;
    (valid.structure as any).sections = ["hero", "services", "contact", "footer"];
    delete (valid as any).hours;
    expect(validate(valid)).toBe(true);
  });
});

describe('brief schema — sections vs data consistency', () => {
  it('rejects services section without services data', () => {
    const invalid = clone(example);
    delete (invalid as any).services;
    expect(validate(invalid)).toBe(false);
  });

  it('rejects hours section without hours data', () => {
    const invalid = clone(example);
    (invalid.structure as any).sections = ["hero", "hours", "footer"];
    delete (invalid as any).hours;
    expect(validate(invalid)).toBe(false);
  });

  it('rejects gallery section without media.gallery', () => {
    const invalid = clone(example);
    (invalid.structure as any).sections = ["hero", "gallery", "footer"];
    (invalid as any).media = {};
    expect(validate(invalid)).toBe(false);
  });

  it('accepts gallery section with media.gallery present', () => {
    const valid = clone(example);
    (valid.structure as any).sections = ["hero", "gallery", "footer"];
    (valid as any).media = { gallery: ["https://example.com/a.jpg"] };
    expect(validate(valid)).toBe(true);
  });
});

describe('brief schema — missing root fields', () => {
  it('rejects without brief_version', () => {
    const invalid = clone(example);
    delete (invalid as any).brief_version;
    expect(validate(invalid)).toBe(false);
  });

  it('rejects without site_type', () => {
    const invalid = clone(example);
    delete (invalid as any).site_type;
    expect(validate(invalid)).toBe(false);
  });

  it('rejects without common', () => {
    const invalid = clone(example);
    delete (invalid as any).common;
    expect(validate(invalid)).toBe(false);
  });

  it('rejects without structure', () => {
    const invalid = clone(example);
    delete (invalid as any).structure;
    expect(validate(invalid)).toBe(false);
  });

  it('rejects structure without sections', () => {
    const invalid = clone(example);
    delete (invalid.structure as any).sections;
    expect(validate(invalid)).toBe(false);
  });

  it('rejects structure without primary_cta', () => {
    const invalid = clone(example);
    delete (invalid.structure as any).primary_cta;
    expect(validate(invalid)).toBe(false);
  });
});

describe('brief schema — combinations of site_type, primary_cta, sections', () => {
  it('accepts personal_brand + phone CTA', () => {
    const valid = clone(example);
    (valid as any).site_type = "personal_brand";
    delete (valid.contacts as any).address;
    delete (valid.contacts as any).city;
    delete (valid as any).hours;
    (valid.structure as any).sections = ["hero", "about", "services", "contact", "footer"];
    (valid.structure as any).primary_cta = "phone";
    expect(validate(valid)).toBe(true);
  });

  it('accepts personal_brand + email CTA without phone', () => {
    const valid = clone(example);
    (valid as any).site_type = "personal_brand";
    (valid as any).contacts = { email: "hello@example.com" };
    delete (valid as any).services;
    delete (valid as any).hours;
    (valid.structure as any).sections = ["hero", "about", "contact", "footer"];
    (valid.structure as any).primary_cta = "email";
    expect(validate(valid)).toBe(true);
  });

  it('accepts agency + form CTA with form_capture', () => {
    const valid = clone(example);
    (valid as any).site_type = "agency";
    delete (valid.contacts as any).address;
    delete (valid.contacts as any).city;
    delete (valid as any).hours;
    (valid.structure as any).sections = ["hero", "services", "contact", "footer"];
    (valid.structure as any).primary_cta = "form";
    (valid as any).functional = { modules: ["form_capture"] };
    expect(validate(valid)).toBe(true);
  });

  it('rejects agency + form CTA without form_capture', () => {
    const invalid = clone(example);
    (invalid as any).site_type = "agency";
    delete (invalid.contacts as any).address;
    delete (invalid.contacts as any).city;
    delete (invalid as any).hours;
    (invalid.structure as any).sections = ["hero", "services", "contact", "footer"];
    (invalid.structure as any).primary_cta = "form";
    (invalid as any).functional = { modules: ["cookie_consent"] };
    expect(validate(invalid)).toBe(false);
  });

  it('rejects local_business + whatsapp CTA without address', () => {
    const invalid = clone(example);
    (invalid as any).contacts = { whatsapp: "+39 333 1234567" };
    (invalid.structure as any).primary_cta = "whatsapp";
    (invalid.structure as any).sections = ["hero", "contact", "footer"];
    delete (invalid as any).services;
    delete (invalid as any).hours;
    expect(validate(invalid)).toBe(false);
  });

  it('accepts local_business + whatsapp CTA with full contacts', () => {
    const valid = clone(example);
    (valid as any).contacts = {
      whatsapp: "+39 333 1234567",
      address: "Via Roma 42, Milano",
      city: "Milano",
    };
    (valid.structure as any).primary_cta = "whatsapp";
    (valid.structure as any).sections = ["hero", "contact", "footer"];
    delete (valid as any).services;
    delete (valid as any).hours;
    expect(validate(valid)).toBe(true);
  });
});