/**
 * Sector-Specific Appointment System Tests
 *
 * Tests the following modules:
 * 1. sector-custom-fields.ts — per-sector form field definitions
 * 2. industry-appointment-types.ts — getIndustryConfig with sector resolution
 * 3. industry-sector-map.ts — industry→sector mapping
 * 4. voice-agent-workflow-templates.ts — workflow templates
 * 5. Integration: sector mapping ↔ custom fields alignment
 */

import {
  getSectorCustomFields,
  SECTOR_CUSTOM_FIELDS,
} from "@/lib/config/sector-custom-fields";

import {
  getIndustryConfig,
  INDUSTRY_APPOINTMENT_TYPES,
} from "@/lib/config/industry-appointment-types";

import {
  getSectorForIndustry,
  SECTOR_KEYS,
  INDUSTRY_TO_SECTOR,
} from "@/lib/config/industry-sector-map";

import { WORKFLOW_TEMPLATES } from "@/lib/config/voice-agent-workflow-templates";

// ── 1. sector-custom-fields.ts ──────────────────────────────────────────────

describe("sector-custom-fields", () => {
  describe("getSectorCustomFields", () => {
    it("returns doctor_specialist and department for health_care", () => {
      const fields = getSectorCustomFields("health_care");
      const keys = fields.map((f) => f.key);
      expect(keys).toContain("doctor_specialist");
      expect(keys).toContain("department");
    });

    it("returns stylist_therapist and treatment_area for beauty_wellness", () => {
      const fields = getSectorCustomFields("beauty_wellness");
      const keys = fields.map((f) => f.key);
      expect(keys).toContain("stylist_therapist");
      expect(keys).toContain("treatment_area");
    });

    it("returns 3 fields for food_hospitality: party_size, dietary_requirements, special_occasion", () => {
      const fields = getSectorCustomFields("food_hospitality");
      const keys = fields.map((f) => f.key);
      expect(fields).toHaveLength(3);
      expect(keys).toContain("party_size");
      expect(keys).toContain("dietary_requirements");
      expect(keys).toContain("special_occasion");
    });

    it("returns property_address, property_type, bedrooms for property_facilities", () => {
      const fields = getSectorCustomFields("property_facilities");
      const keys = fields.map((f) => f.key);
      expect(keys).toContain("property_address");
      expect(keys).toContain("property_type");
      expect(keys).toContain("bedrooms");
    });

    it("returns vehicle_type, pickup_location, return_date for mobility_automotive", () => {
      const fields = getSectorCustomFields("mobility_automotive");
      const keys = fields.map((f) => f.key);
      expect(keys).toContain("vehicle_type");
      expect(keys).toContain("pickup_location");
      expect(keys).toContain("return_date");
    });

    it("returns service_address, issue_description for home_services_trades", () => {
      const fields = getSectorCustomFields("home_services_trades");
      const keys = fields.map((f) => f.key);
      expect(keys).toContain("service_address");
      expect(keys).toContain("issue_description");
    });

    it("returns course_subject, level for education", () => {
      const fields = getSectorCustomFields("education");
      const keys = fields.map((f) => f.key);
      expect(keys).toContain("course_subject");
      expect(keys).toContain("level");
    });

    it("returns event_type, guest_count, venue_preference for events_venues", () => {
      const fields = getSectorCustomFields("events_venues");
      const keys = fields.map((f) => f.key);
      expect(keys).toContain("event_type");
      expect(keys).toContain("guest_count");
      expect(keys).toContain("venue_preference");
    });

    it("returns pet_type, pet_name, pet_weight for pet_services", () => {
      const fields = getSectorCustomFields("pet_services");
      const keys = fields.map((f) => f.key);
      expect(keys).toContain("pet_type");
      expect(keys).toContain("pet_name");
      expect(keys).toContain("pet_weight");
    });

    it("returns program_name, participant_count for nonprofit_community", () => {
      const fields = getSectorCustomFields("nonprofit_community");
      const keys = fields.map((f) => f.key);
      expect(keys).toContain("program_name");
      expect(keys).toContain("participant_count");
    });

    it("returns service_type, reference_number for public_sector", () => {
      const fields = getSectorCustomFields("public_sector");
      const keys = fields.map((f) => f.key);
      expect(keys).toContain("service_type");
      expect(keys).toContain("reference_number");
    });

    it("returns consultant, service_category for retail_services", () => {
      const fields = getSectorCustomFields("retail_services");
      const keys = fields.map((f) => f.key);
      expect(keys).toContain("consultant");
      expect(keys).toContain("service_category");
    });

    it("returns empty array for null", () => {
      expect(getSectorCustomFields(null)).toEqual([]);
    });

    it("returns empty array for undefined", () => {
      expect(getSectorCustomFields(undefined)).toEqual([]);
    });

    it("returns empty array for unknown key", () => {
      expect(getSectorCustomFields("totally_unknown_sector")).toEqual([]);
    });

    it("every field has non-empty labelEn and labelAr", () => {
      for (const [, fields] of Object.entries(SECTOR_CUSTOM_FIELDS)) {
        for (const field of fields) {
          expect(field.labelEn).toBeTruthy();
          expect(typeof field.labelEn).toBe("string");
          expect(field.labelAr).toBeTruthy();
          expect(typeof field.labelAr).toBe("string");
        }
      }
    });

    it("every select-type field has a non-empty options array with value, labelEn, labelAr", () => {
      for (const [, fields] of Object.entries(SECTOR_CUSTOM_FIELDS)) {
        for (const field of fields) {
          if (field.type === "select") {
            expect(field.options).toBeDefined();
            expect(Array.isArray(field.options)).toBe(true);
            expect(field.options!.length).toBeGreaterThan(0);
            for (const opt of field.options!) {
              expect(opt.value).toBeTruthy();
              expect(opt.labelEn).toBeTruthy();
              expect(opt.labelAr).toBeTruthy();
            }
          }
        }
      }
    });
  });
});

// ── 2. industry-appointment-types.ts ────────────────────────────────────────

describe("industry-appointment-types", () => {
  describe("getIndustryConfig — direct key lookup", () => {
    it('returns healthcare config for "healthcare"', () => {
      const config = getIndustryConfig("healthcare");
      expect(config.core.length).toBeGreaterThan(0);
      const coreNames = config.core.map((t) => t.nameEn);
      expect(coreNames).toContain("Consultation");
    });

    it('returns dental config for "dental"', () => {
      const config = getIndustryConfig("dental");
      expect(config.core.length).toBeGreaterThan(0);
      // dental is a distinct config from healthcare
      expect(config).toBe(INDUSTRY_APPOINTMENT_TYPES["dental"]);
    });
  });

  describe("getIndustryConfig — sector resolution (underscore onboarding keys)", () => {
    it('"health_care" resolves to healthcare config (not other/fallback)', () => {
      const config = getIndustryConfig("health_care");
      const healthcareConfig = INDUSTRY_APPOINTMENT_TYPES["healthcare"];
      expect(config).toBe(healthcareConfig);
      expect(config.core.map((t) => t.nameEn)).toContain("Consultation");
    });

    it('"beauty_wellness" resolves to beauty-wellness config', () => {
      const config = getIndustryConfig("beauty_wellness");
      const beautyConfig = INDUSTRY_APPOINTMENT_TYPES["beauty-wellness"];
      expect(config).toBe(beautyConfig);
    });

    it('"food_hospitality" resolves to food-hospitality config', () => {
      const config = getIndustryConfig("food_hospitality");
      const foodConfig = INDUSTRY_APPOINTMENT_TYPES["food-hospitality"];
      expect(config).toBe(foodConfig);
    });

    it('"pet_services" resolves to pet-services or vet config', () => {
      const config = getIndustryConfig("pet_services");
      // Should resolve to a pet/vet config, not the other fallback
      expect(config).not.toBe(INDUSTRY_APPOINTMENT_TYPES.other);
      expect(config.core.length).toBeGreaterThan(0);
    });

    it('"property_facilities" resolves to property-facilities config', () => {
      const config = getIndustryConfig("property_facilities");
      expect(config).not.toBe(INDUSTRY_APPOINTMENT_TYPES.other);
    });

    it('"mobility_automotive" resolves to mobility config', () => {
      const config = getIndustryConfig("mobility_automotive");
      expect(config).not.toBe(INDUSTRY_APPOINTMENT_TYPES.other);
    });
  });

  describe("getIndustryConfig — fallback", () => {
    it("returns other config for null", () => {
      const config = getIndustryConfig(null);
      expect(config).toBe(INDUSTRY_APPOINTMENT_TYPES.other);
    });

    it("returns other config for undefined", () => {
      const config = getIndustryConfig(undefined);
      expect(config).toBe(INDUSTRY_APPOINTMENT_TYPES.other);
    });

    it("returns a valid config for nonexistent key", () => {
      const config = getIndustryConfig("nonexistent_xyz");
      expect(config).toBeDefined();
      expect(config.core.length).toBeGreaterThan(0);
      expect(config.suggested.length).toBeGreaterThan(0);
    });
  });

  describe("getIndustryConfig — structural invariants", () => {
    it("every config has non-empty core and suggested arrays", () => {
      for (const [, config] of Object.entries(INDUSTRY_APPOINTMENT_TYPES)) {
        expect(config.core.length).toBeGreaterThan(0);
        expect(config.suggested.length).toBeGreaterThan(0);
      }
    });

    it("every appointment type has nameEn, nameAr, duration > 0, category, itemType", () => {
      for (const [, config] of Object.entries(INDUSTRY_APPOINTMENT_TYPES)) {
        const allTypes = [...config.core, ...config.suggested];
        for (const t of allTypes) {
          expect(t.nameEn).toBeTruthy();
          expect(t.nameAr).toBeTruthy();
          expect(t.duration).toBeGreaterThan(0);
          expect(t.category).toBeTruthy();
          expect(t.itemType).toBeTruthy();
          expect(
            ["service", "product", "menu_item", "fee", "rental"].includes(
              t.itemType,
            ),
          ).toBe(true);
        }
      }
    });
  });
});

// ── 3. industry-sector-map.ts ───────────────────────────────────────────────

describe("industry-sector-map", () => {
  describe("getSectorForIndustry", () => {
    it('maps "healthcare" to "health_care"', () => {
      expect(getSectorForIndustry("healthcare")).toBe("health_care");
    });

    it('maps "dental" to "health_care"', () => {
      expect(getSectorForIndustry("dental")).toBe("health_care");
    });

    it('maps "beauty-wellness" to "beauty_wellness"', () => {
      expect(getSectorForIndustry("beauty-wellness")).toBe("beauty_wellness");
    });

    it('maps "restaurants-cafes" to "food_hospitality"', () => {
      expect(getSectorForIndustry("restaurants-cafes")).toBe("food_hospitality");
    });

    it('maps "vehicle-rental" to "mobility_automotive"', () => {
      expect(getSectorForIndustry("vehicle-rental")).toBe(
        "mobility_automotive",
      );
    });

    it("returns retail_services for null", () => {
      expect(getSectorForIndustry(null)).toBe("retail_services");
    });

    it("returns retail_services for undefined", () => {
      expect(getSectorForIndustry(undefined)).toBe("retail_services");
    });

    it("returns retail_services for unknown key", () => {
      expect(getSectorForIndustry("bogus_key_12345")).toBe("retail_services");
    });

    // Underscore onboarding keys (the root cause fix)
    it('maps underscore key "health_care" to "health_care" sector', () => {
      expect(getSectorForIndustry("health_care")).toBe("health_care");
    });

    it('maps underscore key "beauty_wellness" to "beauty_wellness" sector', () => {
      expect(getSectorForIndustry("beauty_wellness")).toBe("beauty_wellness");
    });

    it('maps underscore key "food_hospitality" to "food_hospitality" sector', () => {
      expect(getSectorForIndustry("food_hospitality")).toBe("food_hospitality");
    });

    it('maps underscore key "pet_services" to "pet_services" sector', () => {
      expect(getSectorForIndustry("pet_services")).toBe("pet_services");
    });
  });

  describe("SECTOR_KEYS", () => {
    it("has exactly 12 entries", () => {
      expect(SECTOR_KEYS).toHaveLength(12);
    });

    it("contains all expected sector keys", () => {
      const expected = [
        "health_care",
        "beauty_wellness",
        "food_hospitality",
        "retail_services",
        "property_facilities",
        "mobility_automotive",
        "home_services_trades",
        "education",
        "events_venues",
        "pet_services",
        "nonprofit_community",
        "public_sector",
      ];
      for (const key of expected) {
        expect(SECTOR_KEYS).toContain(key);
      }
    });
  });

  describe("INDUSTRY_TO_SECTOR", () => {
    it("every value is a valid sector key", () => {
      const sectorKeySet = new Set<string>(SECTOR_KEYS);
      for (const [, sector] of Object.entries(INDUSTRY_TO_SECTOR)) {
        expect(sectorKeySet.has(sector)).toBe(true);
      }
    });
  });
});

// ── 4. voice-agent-workflow-templates.ts ─────────────────────────────────────

describe("voice-agent-workflow-templates", () => {
  describe("WORKFLOW_TEMPLATES count and identity", () => {
    it("has at least 9 entries (3 original + 6 new)", () => {
      expect(WORKFLOW_TEMPLATES.length).toBeGreaterThanOrEqual(9);
    });

    it("contains all expected template IDs", () => {
      const ids = WORKFLOW_TEMPLATES.map((t) => t.id);
      const expected = [
        "booking_flow",
        "faq_flow",
        "triage_flow",
        "order_flow",
        "rental_flow",
        "enrollment_flow",
        "job_request_flow",
        "event_booking_flow",
        "consultation_flow",
      ];
      for (const id of expected) {
        expect(ids).toContain(id);
      }
    });
  });

  describe("WORKFLOW_TEMPLATES structural invariants", () => {
    it("every template has bilingual name (en + ar non-empty)", () => {
      for (const t of WORKFLOW_TEMPLATES) {
        expect(t.name.en).toBeTruthy();
        expect(typeof t.name.en).toBe("string");
        expect(t.name.ar).toBeTruthy();
        expect(typeof t.name.ar).toBe("string");
      }
    });

    it("every template has bilingual description (en + ar non-empty)", () => {
      for (const t of WORKFLOW_TEMPLATES) {
        expect(t.description.en).toBeTruthy();
        expect(typeof t.description.en).toBe("string");
        expect(t.description.ar).toBeTruthy();
        expect(typeof t.description.ar).toBe("string");
      }
    });

    it('every template has at least one "start" node and one "end" node', () => {
      for (const t of WORKFLOW_TEMPLATES) {
        const types = t.nodes.map((n) => n.type);
        expect(types).toContain("start");
        expect(types).toContain("end");
      }
    });

    it("every template has at least one edge", () => {
      for (const t of WORKFLOW_TEMPLATES) {
        expect(t.edges.length).toBeGreaterThan(0);
      }
    });

    it("every template has customizationFields array", () => {
      for (const t of WORKFLOW_TEMPLATES) {
        expect(Array.isArray(t.customizationFields)).toBe(true);
      }
    });

    it("all node types are valid", () => {
      const validTypes = new Set([
        "start",
        "prompt",
        "tool_call",
        "condition",
        "end",
      ]);
      for (const t of WORKFLOW_TEMPLATES) {
        for (const node of t.nodes) {
          expect(validTypes.has(node.type)).toBe(true);
        }
      }
    });
  });
});

// ── 5. Integration: sector mapping → custom fields alignment ────────────────

describe("Integration: SECTOR_KEYS ↔ custom fields alignment", () => {
  it("every SECTOR_KEY has a non-empty custom fields definition", () => {
    for (const key of SECTOR_KEYS) {
      const fields = getSectorCustomFields(key);
      expect(fields.length).toBeGreaterThan(0);
    }
  });
});
