import { describe, it, expect } from "vitest";
import { getTableConfig } from "drizzle-orm/pg-core";
import * as schema from "./schema";

const tableNames = [
  "users", "accounts", "sessions", "deviceTokens",
  "familyGroups", "familyGroupMembers", "subscriptions",
  "watchlistItems", "exposures",
  "alerts",
  "voiceEnrollments", "voiceAnalyses", "analysisJobs", "analysisResults",
  "spamFeedback", "spamRules",
  "auditLogs", "kpiSnapshots",
  "normalizedAlerts", "correlationGroups",
  "securityReports",
  "waitlistEntries", "blogPosts",
  "propertyWatchlistItems", "propertySnapshots", "propertyChanges",
  "infoBrokers", "removalRequests", "brokerListings",
  "invitations",
];

const enumNames = [
  "userRole", "deviceType", "platform", "familyMemberRole",
  "subscriptionTier", "subscriptionStatus",
  "watchlistType", "exposureSource", "exposureSeverity",
  "alertType", "alertSeverity", "alertChannel",
  "detectionVerdict", "analysisType", "analysisJobStatus",
  "feedbackType", "ruleType", "ruleAction",
  "alertSource", "alertCategory", "normalizedAlertSeverity", "correlationStatus",
  "reportType", "reportStatus",
  "propertyChangeType", "propertyChangeSeverity",
  "brokerCategory", "removalMethod", "removalStatus",
  "invitationStatus",
];

describe("schema exports", () => {
  it("exports all 30 tables", () => {
    for (const name of tableNames) {
      expect((schema as Record<string, unknown>)[name], `Missing table: ${name}`).toBeDefined();
    }
  });

  it("exports all 29 enums", () => {
    for (const name of enumNames) {
      expect((schema as Record<string, unknown>)[name], `Missing enum: ${name}`).toBeDefined();
    }
  });

  it("exports all 26 relation definitions", () => {
    const relationNames = [
      "usersRelations", "accountsRelations", "sessionsRelations", "deviceTokensRelations",
      "familyGroupsRelations", "familyGroupMembersRelations", "subscriptionsRelations",
      "watchlistItemsRelations", "exposuresRelations",
      "alertsRelations",
      "voiceEnrollmentsRelations", "voiceAnalysesRelations", "analysisJobsRelations", "analysisResultsRelations",
      "spamFeedbackRelations", "spamRulesRelations",
      "normalizedAlertsRelations", "correlationGroupsRelations",
      "securityReportsRelations",
      "propertyWatchlistItemsRelations", "propertySnapshotsRelations", "propertyChangesRelations",
      "infoBrokersRelations", "removalRequestsRelations", "brokerListingsRelations",
      "invitationsRelations",
    ];
    for (const name of relationNames) {
      expect((schema as Record<string, unknown>)[name], `Missing relation: ${name}`).toBeDefined();
    }
  });
});

describe("users table", () => {
  const config = getTableConfig(schema.users);

  it("has expected columns", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("id");
    expect(colNames).toContain("email");
    expect(colNames).toContain("email_verified");
    expect(colNames).toContain("name");
    expect(colNames).toContain("image");
    expect(colNames).toContain("role");
    expect(colNames).toContain("stripe_customer_id");
    expect(colNames).toContain("deleted_at");
    expect(colNames).toContain("created_at");
    expect(colNames).toContain("updated_at");
  });

  it("has 10 columns", () => {
    expect(config.columns).toHaveLength(10);
  });

  it("has 3 indexes", () => {
    expect(config.indexes.length).toBe(3);
  });
});

describe("accounts table", () => {
  const config = getTableConfig(schema.accounts);

  it("has user_id, provider, provider_account_id", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("user_id");
    expect(colNames).toContain("provider");
    expect(colNames).toContain("provider_account_id");
  });

  it("has expected columns with correct count", () => {
    expect(config.columns.length).toBeGreaterThanOrEqual(9);
  });
});

describe("subscriptions table", () => {
  const config = getTableConfig(schema.subscriptions);

  it("has expected columns with correct count", () => {
    expect(config.columns.length).toBeGreaterThanOrEqual(11);
  });

  it("has stripe_id, tier, status columns", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("stripe_id");
    expect(colNames).toContain("tier");
    expect(colNames).toContain("status");
    expect(colNames).toContain("current_period_start");
    expect(colNames).toContain("current_period_end");
  });
});

describe("alerts table", () => {
  const config = getTableConfig(schema.alerts);

  it("has foreign key columns", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("subscription_id");
    expect(colNames).toContain("user_id");
    expect(colNames).toContain("exposure_id");
  });

  it("has channel array column", () => {
    const channelCol = config.columns.find((c) => c.name === "channel");
    expect(channelCol).toBeDefined();
  });
});

describe("blogPosts table", () => {
  const config = getTableConfig(schema.blogPosts);

  it("has tags array column", () => {
    const tagsCol = config.columns.find((c) => c.name === "tags");
    expect(tagsCol).toBeDefined();
  });

  it("has all expected columns", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("id");
    expect(colNames).toContain("slug");
    expect(colNames).toContain("title");
    expect(colNames).toContain("content");
    expect(colNames).toContain("tags");
    expect(colNames).toContain("published");
    expect(colNames).toContain("published_at");
    expect(colNames).toContain("view_count");
  });
});

describe("normalizedAlerts table", () => {
  const config = getTableConfig(schema.normalizedAlerts);

  it("has source_alert_id column", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("source_alert_id");
  });

  it("has entities column", () => {
    expect(config.columns.find((c) => c.name === "entities")).toBeDefined();
  });
});

describe("watchlistItems table", () => {
  const config = getTableConfig(schema.watchlistItems);

  it("has all expected columns", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("subscription_id");
    expect(colNames).toContain("type");
    expect(colNames).toContain("value");
    expect(colNames).toContain("hash");
    expect(colNames).toContain("is_active");
  });
});

describe("exposures table", () => {
  const config = getTableConfig(schema.exposures);

  it("has metadata jsonb, severity, detected_at", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("metadata");
    expect(colNames).toContain("severity");
    expect(colNames).toContain("detected_at");
    expect(colNames).toContain("is_first_time");
  });
});

describe("voiceEnrollments table", () => {
  const config = getTableConfig(schema.voiceEnrollments);

  it("has voice_hash and audio_metadata", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("voice_hash");
    expect(colNames).toContain("audio_metadata");
    expect(colNames).toContain("is_active");
  });
});

describe("analysisJobs table", () => {
  const config = getTableConfig(schema.analysisJobs);

  it("has analysis_type, status, error_message", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("analysis_type");
    expect(colNames).toContain("status");
    expect(colNames).toContain("error_message");
    expect(colNames).toContain("audio_file_path");
  });
});

describe("analysisResults table", () => {
  const config = getTableConfig(schema.analysisResults);

  it("has analysis_job_id with unique", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("analysis_job_id");
    expect(colNames).toContain("synthetic_score");
    expect(colNames).toContain("verdict");
    expect(colNames).toContain("processing_time_ms");
  });
});

describe("spamFeedback table", () => {
  const config = getTableConfig(schema.spamFeedback);

  it("has phone_number, phone_number_hash, is_spam", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("phone_number");
    expect(colNames).toContain("phone_number_hash");
    expect(colNames).toContain("is_spam");
    expect(colNames).toContain("feedback_type");
  });
});

describe("spamRules table", () => {
  const config = getTableConfig(schema.spamRules);

  it("has rule_type, pattern, action", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("rule_type");
    expect(colNames).toContain("pattern");
    expect(colNames).toContain("action");
    expect(colNames).toContain("is_global");
  });
});

describe("auditLogs table", () => {
  const config = getTableConfig(schema.auditLogs);

  it("has action, resource, resource_id", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("action");
    expect(colNames).toContain("resource");
    expect(colNames).toContain("resource_id");
    expect(colNames).toContain("ip_address");
    expect(colNames).toContain("user_agent");
  });
});

describe("kpiSnapshots table", () => {
  const config = getTableConfig(schema.kpiSnapshots);

  it("has date, metric_name, metric_value", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("date");
    expect(colNames).toContain("metric_name");
    expect(colNames).toContain("metric_value");
  });
});

describe("propertyWatchlistItems table", () => {
  const config = getTableConfig(schema.propertyWatchlistItems);

  it("has address, street_address, parcel_id", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("address");
    expect(colNames).toContain("street_address");
    expect(colNames).toContain("parcel_id");
    expect(colNames).toContain("latitude");
    expect(colNames).toContain("longitude");
  });
});

describe("propertySnapshots table", () => {
  const config = getTableConfig(schema.propertySnapshots);

  it("has captured_at, owner_name, address jsonb", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("captured_at");
    expect(colNames).toContain("owner_name");
    expect(colNames).toContain("address");
    expect(colNames).toContain("property_type");
    expect(colNames).toContain("tax_amount");
    expect(colNames).toContain("lien_count");
  });
});

describe("propertyChanges table", () => {
  const config = getTableConfig(schema.propertyChanges);

  it("has change_type, severity, details", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("change_type");
    expect(colNames).toContain("severity");
    expect(colNames).toContain("details");
    expect(colNames).toContain("detected_at");
  });
});

describe("infoBrokers table", () => {
  const config = getTableConfig(schema.infoBrokers);

  it("has name, domain, category", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("name");
    expect(colNames).toContain("domain");
    expect(colNames).toContain("category");
    expect(colNames).toContain("removal_method");
    expect(colNames).toContain("estimated_days");
  });
});

describe("removalRequests table", () => {
  const config = getTableConfig(schema.removalRequests);

  it("has personal_info jsonb, status, attempts", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("personal_info");
    expect(colNames).toContain("status");
    expect(colNames).toContain("attempts");
    expect(colNames).toContain("next_retry_at");
    expect(colNames).toContain("error");
    expect(colNames).toContain("notes");
  });
});

describe("brokerListings table", () => {
  const config = getTableConfig(schema.brokerListings);

  it("has url, data_found, screenshot_url", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("url");
    expect(colNames).toContain("data_found");
    expect(colNames).toContain("screenshot_url");
    expect(colNames).toContain("is_removed");
  });
});

describe("correlationGroups table", () => {
  const config = getTableConfig(schema.correlationGroups);

  it("has entities, highest_severity, alert_count", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("entities");
    expect(colNames).toContain("highest_severity");
    expect(colNames).toContain("alert_count");
    expect(colNames).toContain("summary");
  });
});

describe("securityReports table", () => {
  const config = getTableConfig(schema.securityReports);

  it("has period_start, period_end, pdf_url", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("period_start");
    expect(colNames).toContain("period_end");
    expect(colNames).toContain("pdf_url");
    expect(colNames).toContain("html_content");
    expect(colNames).toContain("report_type");
    expect(colNames).toContain("status");
  });
});

describe("waitlistEntries table", () => {
  const config = getTableConfig(schema.waitlistEntries);

  it("has email, source, utm tracking, conversion tracking", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("email");
    expect(colNames).toContain("source");
    expect(colNames).toContain("utm_source");
    expect(colNames).toContain("utm_medium");
    expect(colNames).toContain("utm_campaign");
    expect(colNames).toContain("converted_at");
    expect(colNames).toContain("converted_to_user_id");
  });
});

describe("familyGroups table", () => {
  const config = getTableConfig(schema.familyGroups);

  it("has owner_id, name", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("owner_id");
    expect(colNames).toContain("name");
  });
});

describe("familyGroupMembers table", () => {
  const config = getTableConfig(schema.familyGroupMembers);

  it("has group_id, user_id, role, joined_at", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("group_id");
    expect(colNames).toContain("user_id");
    expect(colNames).toContain("role");
    expect(colNames).toContain("joined_at");
  });
});

describe("sessions table", () => {
  const config = getTableConfig(schema.sessions);

  it("has session_token, expires", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("session_token");
    expect(colNames).toContain("expires");
    expect(colNames).toContain("user_id");
  });
});

describe("deviceTokens table", () => {
  const config = getTableConfig(schema.deviceTokens);

  it("has device_type, platform, token, is_active", () => {
    const colNames = config.columns.map((c) => c.name);
    expect(colNames).toContain("device_type");
    expect(colNames).toContain("platform");
    expect(colNames).toContain("token");
    expect(colNames).toContain("is_active");
    expect(colNames).toContain("last_used_at");
  });
});
