import argparse
import json
from pathlib import Path

from app.core.database import SessionLocal
from app.models.accounting_dimensions import AccountingDimension, AccountingDimensionValue
from sqlalchemy.exc import IntegrityError


DEFAULT_FIXTURE = {
    "dimensions": [
        {
            "code": "DEPT",
            "name": "Cost Center",
            "description": "Organizational cost centers / departments",
            "dimension_type": "organizational",
            "scope": "global",
            "is_active": True,
            "is_required": True,
            "allow_multiple_values": False,
            "supports_hierarchy": True,
            "max_hierarchy_levels": 3,
            "display_order": 1,
            "values": [
                {
                    "code": "HQ",
                    "name": "Head Office",
                    "description": "Headquarters",
                    "is_active": True,
                    "hierarchy_level": 1,
                },
                {
                    "code": "SALES",
                    "name": "Sales Department",
                    "description": "Sales",
                    "is_active": True,
                    "hierarchy_level": 1,
                },
                {
                    "code": "IT",
                    "name": "IT Department",
                    "description": "IT",
                    "is_active": True,
                    "hierarchy_level": 1,
                },
                {
                    "code": "OPS",
                    "name": "Operations",
                    "description": "Operations",
                    "is_active": True,
                    "hierarchy_level": 1,
                },
            ],
        },
        {
            "code": "PROJ",
            "name": "Project",
            "description": "Projects for revenue/capex tracking",
            "dimension_type": "project",
            "scope": "global",
            "is_active": True,
            "is_required": True,
            "allow_multiple_values": False,
            "supports_hierarchy": False,
            "max_hierarchy_levels": 1,
            "display_order": 2,
            "values": [
                {
                    "code": "ALPHA",
                    "name": "Project Alpha",
                    "description": "Alpha rollout",
                    "is_active": True,
                },
                {
                    "code": "BETA",
                    "name": "Project Beta",
                    "description": "Beta expansion",
                    "is_active": True,
                },
                {
                    "code": "CAPEX24",
                    "name": "Capex FY24",
                    "description": "Capex program FY24",
                    "is_active": True,
                },
            ],
        },
        {
            "code": "GEO",
            "name": "Geography",
            "description": "Geographical region/country",
            "dimension_type": "geographical",
            "scope": "global",
            "is_active": True,
            "is_required": False,
            "allow_multiple_values": False,
            "supports_hierarchy": True,
            "max_hierarchy_levels": 3,
            "display_order": 3,
            "values": [
                {
                    "code": "AFR",
                    "name": "Africa",
                    "description": "Region Africa",
                    "is_active": True,
                    "hierarchy_level": 1,
                },
                {
                    "code": "BW",
                    "name": "Botswana",
                    "description": "Botswana",
                    "is_active": True,
                    "parent_code": "AFR",
                    "hierarchy_level": 2,
                },
                {
                    "code": "ZA",
                    "name": "South Africa",
                    "description": "South Africa",
                    "is_active": True,
                    "parent_code": "AFR",
                    "hierarchy_level": 2,
                },
            ],
        },
    ]
}


def get_or_create_dimension(db, code, defaults):
    dim = db.query(AccountingDimension).filter_by(code=code).first()
    if dim:
        return dim
    dim = AccountingDimension(code=code, **defaults)
    db.add(dim)
    db.flush()
    return dim


def get_or_create_value(db, dimension_id, code, defaults):
    val = (
        db.query(AccountingDimensionValue)
        .filter_by(dimension_id=dimension_id, code=code)
        .first()
    )
    if val:
        return val
    val = AccountingDimensionValue(dimension_id=dimension_id, code=code, **defaults)
    db.add(val)
    db.flush()
    return val


def seed_from_fixture(db, fixture):
    for dim in fixture.get("dimensions", []):
        dim_data = dim.copy()
        code = dim_data.pop("code")
        values = dim_data.pop("values", [])
        dimension = get_or_create_dimension(db, code=code, defaults=dim_data)

        value_lookup = {}
        for val in values:
            val_data = val.copy()
            value_code = val_data.pop("code")
            parent_code = val_data.pop("parent_code", None)

            if parent_code and parent_code in value_lookup:
                val_data["parent_value_id"] = value_lookup[parent_code]

            value = get_or_create_value(
                db,
                dimension_id=dimension.id,
                code=value_code,
                defaults=val_data,
            )
            value_lookup[value_code] = value.id


def load_fixture(path):
    fixture_path = Path(path)
    if not fixture_path.exists():
        raise FileNotFoundError(f"Fixture not found: {fixture_path}")
    with fixture_path.open() as f:
        return json.load(f)


def parse_args():
    parser = argparse.ArgumentParser(description="Seed accounting dimensions")
    parser.add_argument(
        "--fixture",
        type=str,
        help="Path to a JSON fixture file. Defaults to built-in sample data.",
    )
    return parser.parse_args()


def main():
    args = parse_args()
    fixture = load_fixture(args.fixture) if args.fixture else DEFAULT_FIXTURE

    db = SessionLocal()
    try:
        seed_from_fixture(db, fixture)
        db.commit()
        print("Test dimensions seeded (idempotent).")
    except IntegrityError as e:
        db.rollback()
        print(f"Integrity error: {e}")
    finally:
        db.close()


if __name__ == "__main__":
    main()
