"""prospecting: initial tables for lead discovery and campaign management

Revision ID: prospecting_001
Revises: cms_002
Create Date: 2026-02-27
"""
import sqlalchemy as sa

from alembic import op

revision = "prospecting_001"
down_revision = "cms_002"
branch_labels = None
depends_on = None


def upgrade() -> None:
    # --- prospects ---
    op.create_table(
        "prospects",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("channel", sa.String(10), nullable=False, server_default="digital"),
        sa.Column("business_name", sa.String(255), nullable=True),
        sa.Column("domain_name", sa.String(255), nullable=True, unique=True, index=True),
        sa.Column("status", sa.String(20), nullable=False, server_default="pending"),
        sa.Column("source", sa.String(100), nullable=True),
        sa.Column("has_website", sa.Boolean(), nullable=True),
        sa.Column("uses_https", sa.Boolean(), nullable=True),
        sa.Column("http_status_code", sa.Integer(), nullable=True),
        sa.Column("redirect_url", sa.Text(), nullable=True),
        sa.Column("address", sa.String(500), nullable=True),
        sa.Column("city", sa.String(100), nullable=True),
        sa.Column("postal_code", sa.String(10), nullable=True),
        sa.Column("country", sa.String(2), nullable=False, server_default="LU"),
        sa.Column("notes", sa.Text(), nullable=True),
        sa.Column("tags", sa.Text(), nullable=True),
        sa.Column("captured_by_user_id", sa.Integer(), nullable=True),
        sa.Column("location_lat", sa.Float(), nullable=True),
        sa.Column("location_lng", sa.Float(), nullable=True),
        sa.Column("last_http_check_at", sa.DateTime(), nullable=True),
        sa.Column("last_tech_scan_at", sa.DateTime(), nullable=True),
        sa.Column("last_perf_scan_at", sa.DateTime(), nullable=True),
        sa.Column("last_contact_scrape_at", sa.DateTime(), nullable=True),
        sa.Column("created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
    )

    # --- prospect_tech_profiles ---
    op.create_table(
        "prospect_tech_profiles",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("prospect_id", sa.Integer(), sa.ForeignKey("prospects.id", ondelete="CASCADE"), nullable=False, unique=True),
        sa.Column("cms", sa.String(100), nullable=True),
        sa.Column("cms_version", sa.String(50), nullable=True),
        sa.Column("server", sa.String(100), nullable=True),
        sa.Column("server_version", sa.String(50), nullable=True),
        sa.Column("hosting_provider", sa.String(100), nullable=True),
        sa.Column("cdn", sa.String(100), nullable=True),
        sa.Column("has_valid_cert", sa.Boolean(), nullable=True),
        sa.Column("cert_issuer", sa.String(200), nullable=True),
        sa.Column("cert_expires_at", sa.DateTime(), nullable=True),
        sa.Column("js_framework", sa.String(100), nullable=True),
        sa.Column("analytics", sa.String(200), nullable=True),
        sa.Column("tag_manager", sa.String(100), nullable=True),
        sa.Column("ecommerce_platform", sa.String(100), nullable=True),
        sa.Column("tech_stack_json", sa.Text(), nullable=True),
        sa.Column("scan_source", sa.String(50), nullable=True),
        sa.Column("scan_error", sa.Text(), nullable=True),
        sa.Column("created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
    )

    # --- prospect_performance_profiles ---
    op.create_table(
        "prospect_performance_profiles",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("prospect_id", sa.Integer(), sa.ForeignKey("prospects.id", ondelete="CASCADE"), nullable=False, unique=True),
        sa.Column("performance_score", sa.Integer(), nullable=True),
        sa.Column("accessibility_score", sa.Integer(), nullable=True),
        sa.Column("best_practices_score", sa.Integer(), nullable=True),
        sa.Column("seo_score", sa.Integer(), nullable=True),
        sa.Column("first_contentful_paint_ms", sa.Integer(), nullable=True),
        sa.Column("largest_contentful_paint_ms", sa.Integer(), nullable=True),
        sa.Column("total_blocking_time_ms", sa.Integer(), nullable=True),
        sa.Column("cumulative_layout_shift", sa.Float(), nullable=True),
        sa.Column("speed_index", sa.Integer(), nullable=True),
        sa.Column("time_to_interactive_ms", sa.Integer(), nullable=True),
        sa.Column("is_mobile_friendly", sa.Boolean(), nullable=True),
        sa.Column("viewport_configured", sa.Boolean(), nullable=True),
        sa.Column("font_size_ok", sa.Boolean(), nullable=True),
        sa.Column("tap_targets_ok", sa.Boolean(), nullable=True),
        sa.Column("total_bytes", sa.Integer(), nullable=True),
        sa.Column("html_bytes", sa.Integer(), nullable=True),
        sa.Column("css_bytes", sa.Integer(), nullable=True),
        sa.Column("js_bytes", sa.Integer(), nullable=True),
        sa.Column("image_bytes", sa.Integer(), nullable=True),
        sa.Column("font_bytes", sa.Integer(), nullable=True),
        sa.Column("total_requests", sa.Integer(), nullable=True),
        sa.Column("js_requests", sa.Integer(), nullable=True),
        sa.Column("css_requests", sa.Integer(), nullable=True),
        sa.Column("image_requests", sa.Integer(), nullable=True),
        sa.Column("lighthouse_json", sa.Text(), nullable=True),
        sa.Column("scan_strategy", sa.String(20), nullable=True),
        sa.Column("scan_error", sa.Text(), nullable=True),
        sa.Column("created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
    )

    # --- prospect_scores ---
    op.create_table(
        "prospect_scores",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("prospect_id", sa.Integer(), sa.ForeignKey("prospects.id", ondelete="CASCADE"), nullable=False, unique=True),
        sa.Column("score", sa.Integer(), nullable=False, server_default="0", index=True),
        sa.Column("technical_health_score", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("modernity_score", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("business_value_score", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("engagement_score", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("reason_flags", sa.Text(), nullable=True),
        sa.Column("score_breakdown", sa.Text(), nullable=True),
        sa.Column("lead_tier", sa.String(20), nullable=True, index=True),
        sa.Column("notes", sa.Text(), nullable=True),
        sa.Column("created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
    )

    # --- prospect_contacts ---
    op.create_table(
        "prospect_contacts",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("prospect_id", sa.Integer(), sa.ForeignKey("prospects.id", ondelete="CASCADE"), nullable=False, index=True),
        sa.Column("contact_type", sa.String(20), nullable=False),
        sa.Column("value", sa.String(500), nullable=False),
        sa.Column("label", sa.String(100), nullable=True),
        sa.Column("source_url", sa.Text(), nullable=True),
        sa.Column("source_element", sa.String(100), nullable=True),
        sa.Column("is_validated", sa.Boolean(), nullable=False, server_default="0"),
        sa.Column("validation_error", sa.Text(), nullable=True),
        sa.Column("is_primary", sa.Boolean(), nullable=False, server_default="0"),
        sa.Column("created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
    )

    # --- prospect_scan_jobs ---
    op.create_table(
        "prospect_scan_jobs",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("job_type", sa.String(30), nullable=False),
        sa.Column("status", sa.String(20), nullable=False, server_default="pending"),
        sa.Column("total_items", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("processed_items", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("failed_items", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("skipped_items", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("started_at", sa.DateTime(), nullable=True),
        sa.Column("completed_at", sa.DateTime(), nullable=True),
        sa.Column("config", sa.Text(), nullable=True),
        sa.Column("result_summary", sa.Text(), nullable=True),
        sa.Column("error_log", sa.Text(), nullable=True),
        sa.Column("source_file", sa.String(500), nullable=True),
        sa.Column("celery_task_id", sa.String(255), nullable=True),
        sa.Column("created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
    )

    # --- prospect_interactions ---
    op.create_table(
        "prospect_interactions",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("prospect_id", sa.Integer(), sa.ForeignKey("prospects.id", ondelete="CASCADE"), nullable=False, index=True),
        sa.Column("interaction_type", sa.String(20), nullable=False),
        sa.Column("subject", sa.String(255), nullable=True),
        sa.Column("notes", sa.Text(), nullable=True),
        sa.Column("outcome", sa.String(20), nullable=True),
        sa.Column("next_action", sa.String(255), nullable=True),
        sa.Column("next_action_date", sa.Date(), nullable=True),
        sa.Column("created_by_user_id", sa.Integer(), nullable=False),
        sa.Column("created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
    )

    # --- campaign_templates ---
    op.create_table(
        "campaign_templates",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("name", sa.String(255), nullable=False),
        sa.Column("lead_type", sa.String(30), nullable=False),
        sa.Column("channel", sa.String(20), nullable=False, server_default="email"),
        sa.Column("language", sa.String(5), nullable=False, server_default="fr"),
        sa.Column("subject_template", sa.String(500), nullable=True),
        sa.Column("body_template", sa.Text(), nullable=False),
        sa.Column("is_active", sa.Boolean(), nullable=False, server_default="1"),
        sa.Column("created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
    )

    # --- campaign_sends ---
    op.create_table(
        "campaign_sends",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("template_id", sa.Integer(), sa.ForeignKey("campaign_templates.id", ondelete="SET NULL"), nullable=True),
        sa.Column("prospect_id", sa.Integer(), sa.ForeignKey("prospects.id", ondelete="CASCADE"), nullable=False, index=True),
        sa.Column("channel", sa.String(20), nullable=False),
        sa.Column("rendered_subject", sa.String(500), nullable=True),
        sa.Column("rendered_body", sa.Text(), nullable=True),
        sa.Column("status", sa.String(20), nullable=False, server_default="draft"),
        sa.Column("sent_at", sa.DateTime(), nullable=True),
        sa.Column("sent_by_user_id", sa.Integer(), nullable=True),
        sa.Column("created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
    )


def downgrade() -> None:
    op.drop_table("campaign_sends")
    op.drop_table("campaign_templates")
    op.drop_table("prospect_interactions")
    op.drop_table("prospect_scan_jobs")
    op.drop_table("prospect_contacts")
    op.drop_table("prospect_scores")
    op.drop_table("prospect_performance_profiles")
    op.drop_table("prospect_tech_profiles")
    op.drop_table("prospects")
