from dataclasses import dataclass
from typing import Literal

@dataclass
class NaceCode:
    number: str
    description: str
    is_correted: bool = False
    correction_ranking: int | None = None


@dataclass
class Address:
    source: str
    street: str | None = None
    number: str | None = None
    city: str | None = None
    postal_code: str | None = None
    additionnal_address_info: str | None = None
    scraped_address: str | None = None
    last_update: str | None = None

@dataclass
class Email:
    source: str
    email: str

@dataclass
class Phone:
    source: str
    phone: str

@dataclass
class Website:
    source: str
    website: str

@dataclass
class BoardMember:
    is_company: bool
    function: str
    name: str
    start_date: str
    linked_company_number: str | None = None

@dataclass
class SocialNetwork:
    name: str
    url: str

@dataclass
class Establishment:
    establishment_number: str
    status: str | None = None
    start_date: str | None = None
    country: Literal["BE"] = "BE"
    name: str | None = None
    name_fr: str | None = None
    name_nl: str | None = None
    name_last_update: str | None = None
    social_networks: list[SocialNetwork] | None = None
    
    # These can have multiple values found on different sources
    # The best value is the one in best_address (re-computed on a regular basis)
    best_address: str | None = None
    addresses: list[Address] | None = None
    best_email: str | None = None
    emails: list[Email] | None = None
    best_phone: str | None = None
    phones: list[Phone] | None = None
    best_website: str | None = None
    websites: list[Website] | None = None
    
    end_date: str | None = None
    nace_codes: list[NaceCode] | None = None
    is_nace_codes_corrected: bool = False

@dataclass
class Company:
    # A combination of country ISO code and country_company_id in format: BE_1234567890
    inoopa_id: str
    # VAT number in Belgium for ex, SIRET in France,...
    company_number: str
    country: Literal["BE", "FR", "NL"] = "BE"
    legal_situation: str | None = None
    status: str | None = None
    start_date: str | None = None
    entity_type: str | None = None
    legal_form: str | None = None
    # MongoDB id initialized when the company is created in the DB
    _id: str | None = None
    
    # These can have multiple values found on different sources
    # The best value is the one in best_address (re-computed on a regular basis)
    best_address: str | None = None
    addresses: list[Address] | None = None
    best_email: str | None = None
    emails: list[Email] | None = None
    best_phone: str | None = None
    phones: list[Phone] | None = None
    best_website: str | None = None
    websites: list[Website] | None = None
    
    name: str | None = None
    name_fr: str | None = None
    name_nl: str | None = None
    name_last_update: str | None = None
    social_networks: list[SocialNetwork] | None = None
    number_of_establishments: int | None = None
    establishments: list[Establishment] | None = None
    end_date: str | None = None
    legal_situation_last_update: str | None = None
    legal_form_last_update: str | None = None
    board_members: list[BoardMember] | None = None
    nace_codes: list[NaceCode] | None = None
    is_nace_codes_corrected: bool | None = False
    employee_category_code: int | None = None
    employee_category_formatted: str | None = None

def convert_dict_to_company(company_dict: dict) -> Company:
    """
    Convert a dict to a Company object.
    """
    # Convert nested dictionaries for addresses, emails, etc.
    addresses = [Address(**addr) for addr in company_dict.get('addresses', []) or []]
    emails = [Email(**email) for email in company_dict.get('emails', []) or []]
    phones = [Phone(**phone) for phone in company_dict.get('phones', []) or []]
    websites = [Website(**website)for website in company_dict.get('websites', []) or []]
    social_networks = [SocialNetwork(**sn) for sn in company_dict.get('social_networks', []) or []]
    board_members = [BoardMember(**bm) for bm in company_dict.get('board_members', []) or []]
    nace_codes = [NaceCode(**nc) for nc in company_dict.get('nace_codes', []) or []]

    # Handle nested establishments
    establishments = []
    for est in company_dict.get('establishments', []):
        est_addresses = [Address(**addr) for addr in est.get('addresses', []) or []]
        est_emails = [Email(**email) for email in est.get('emails', []) or []]
        est_phones = [Phone(**phone) for phone in est.get('phones', []) or []]
        est_websites = [Website(**website) for website in est.get('websites', []) or []]
        est_social_networks = [SocialNetwork(**sn) for sn in est.get('social_networks', []) or []]
        est_nace_codes = [NaceCode(**nc) for nc in est.get('nace_codes', []) or []]

        establishments.append(Establishment(
            establishment_number=est.get('establishment_number'),
            status=est.get('status'),
            start_date=est.get('start_date'),
            country=est.get('country', 'BE'),
            name=est.get('name'),
            name_fr=est.get('name_fr'),
            name_nl=est.get('name_nl'),
            name_last_update=est.get('name_last_update'),
            social_networks=est_social_networks,
            best_address=est.get('best_address'),
            addresses=est_addresses,
            best_email=est.get('best_email'),
            emails=est_emails,
            best_phone=est.get('best_phone'),
            phones=est_phones,
            best_website=est.get('best_website'),
            websites=est_websites,
            end_date=est.get('end_date'),
            nace_codes=est_nace_codes,
            is_nace_codes_corrected=est.get('is_nace_codes_corrected', False)
        ))

    # Create the Company instance
    return Company(
        inoopa_id=company_dict.get('inoopa_id'),
        company_number=company_dict.get('company_number'),
        country=company_dict.get('country', 'BE'),
        legal_situation=company_dict.get('legal_situation'),
        status=company_dict.get('status'),
        start_date=company_dict.get('start_date'),
        entity_type=company_dict.get('entity_type'),
        legal_form=company_dict.get('legal_form'),
        _id=company_dict.get('_id'),
        best_address=company_dict.get('best_address'),
        addresses=addresses,
        best_email=company_dict.get('best_email'),
        emails=emails,
        best_phone=company_dict.get('best_phone'),
        phones=phones,
        best_website=company_dict.get('best_website'),
        websites=websites,
        name=company_dict.get('name'),
        name_fr=company_dict.get('name_fr'),
        name_nl=company_dict.get('name_nl'),
        name_last_update=company_dict.get('name_last_update'),
        social_networks=social_networks,
        number_of_establishments=company_dict.get('number_of_establishments'),
        establishments=establishments,
        end_date=company_dict.get('end_date'),
        legal_situation_last_update=company_dict.get('legal_situation_last_update'),
        legal_form_last_update=company_dict.get('legal_form_last_update'),
        board_members=board_members,
        nace_codes=nace_codes,
        is_nace_codes_corrected=company_dict.get('is_nace_codes_corrected', False),
        employee_category_code=company_dict.get('employee_category_code'),
        employee_category_formatted=company_dict.get('employee_category_formatted')
    )