"Buyers and Targets router"
from enum import Enum  # Add this import at the top of your file
from typing import Any, Dict, List

from fastapi import APIRouter, HTTPException

from models.buyers_targets import BuyersTargets, BuyersTargetsInfoModel
from services.company_profile.data_classes.company_info import (
    CompanyInfoModelSql, FundInfoModelSql)
from services.sql.buyers_targets_info import (BuyersTargetsInfo,
                                              BuyersTargetsRecordType)
from utils.dynamo_db import DynamoDB
from utils.logger import ServiceLogger
from utils.mysql_db import MySQLDB
from utils.redis_cache import redis_cache  # Import the redis_cache decorator

service_logger = ServiceLogger()
logger = service_logger.get_logger("INFO")


buyers_targets = APIRouter(
    prefix="/buyers_targets",
    tags=["buyers_targets"],
    responses={404: {"description": "Not found"}},
    dependencies=[],  # add dependencies here
)


class SearchType(str, Enum):
    "Search type for buyers and targets"
    COMPANY = "company"
    INVESTOR = "investor"
    BOTH = "both"


mysql_db = MySQLDB()  # Ensure a single instance is created


@buyers_targets.get("/search", response_model=List[BuyersTargets])
async def search_company_info(
    search_term: str,
    search_type: SearchType = SearchType.BOTH,
    limit: int = 10,
) -> List[BuyersTargets]:
    """
    Search for company_name, root_url, or ticker in the company_info and fund_info tables.
    """
    results = []

    async def perform_search(model, search_type):
        filters, order_by = model.search_filters(search_term)
        search_results = await mysql_db.execute_query(
            model=model,
            filters=filters,
            order_by=order_by,
            limit=limit,
        )
        results.extend(
            {**result.to_dict(), "target_type": search_type}
            for result in search_results
        )

    try:
        if search_type in {SearchType.COMPANY, SearchType.BOTH}:
            await perform_search(CompanyInfoModelSql, SearchType.COMPANY)

        if search_type in {SearchType.INVESTOR, SearchType.BOTH}:
            await perform_search(FundInfoModelSql, SearchType.INVESTOR)

        return results

    except Exception as e:
        raise HTTPException(status_code=400, detail={"message": str(e)}) from e


@buyers_targets.post("/add", response_model=Dict[str, Any])
async def save_buyers_targets(
    project_id: str, root_url: str, search_type: SearchType, record_type_id: int
):
    """
    Retrieve company information based on root_url and search_type.
    """
    try:
        db = DynamoDB()
        if search_type == SearchType.COMPANY:
            table = db.company_info_table
        elif search_type == SearchType.INVESTOR:
            table = db.fund_info_table
        else:
            raise HTTPException(status_code=400, detail="Invalid search type")

        response = db.get_item(table, root_url)

        if response is None:
            raise HTTPException(status_code=404, detail="Item not found")

        record_data = {
            "company_id": response.get("root_url"),
            "company_url": response.get("root_url"),
            "company_name": response.get("company_name"),
            "project_id": project_id,
            "logo_url": (
                response.get("logo", {}).get("logo_url")
                if response.get("logo")
                else None
            ),
            "record_type_id": record_type_id,
            "category_name": response.get("sector"),
        }

        # Insert the new record into the database
        new_record = await BuyersTargetsInfo.insert_new_record(mysql_db, **record_data)

        if new_record is None:
            raise HTTPException(status_code=400, detail="Failed to save buyers targets")

        return new_record.to_dict()

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e)) from e


@buyers_targets.get("/get_by_record_type")
async def get_buyers_targets_by_record_type(
    record_type_id: int, project_id: str
) -> List[BuyersTargetsInfoModel]:
    """
    Retrieve buyers_targets based on record_type_id.
    """
    try:
        # Define filters based on record_type_id
        filters = [
            BuyersTargetsInfo.record_type_id == record_type_id,
            BuyersTargetsInfo.project_id == project_id,
        ]

        # Query the database
        results = await mysql_db.execute_query(
            model=BuyersTargetsInfo,  # Use the table attribute if needed
            filters=filters,
        )

        # Convert results to a list of dictionaries
        return [result.to_dict() for result in results]

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e)) from e


@buyers_targets.get("/record_types", response_model=List[Dict[str, Any]])
# @redis_cache(ttl=300)
async def get_record_types() -> List[Dict[str, Any]]:
    """
    Retrieve all record types from the BuyersTargetsRecordType model.
    """
    try:
        # Query the database for all record types
        results = await mysql_db.execute_query(model=BuyersTargetsRecordType)

        # Convert results to a list of dictionaries
        return [result.to_dict() for result in results]

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e)) from e


@buyers_targets.delete("/delete/{record_id}", response_model=Dict[str, Any])
async def delete_buyers_target(record_id: int) -> Dict[str, Any]:
    """
    Delete a buyers_targets record based on record_id.
    """
    try:
        deleted_record = await mysql_db.delete_record(
            model=BuyersTargetsInfo,
            record_id=record_id,
        )

        if not deleted_record:
            raise HTTPException(status_code=404, detail="Record not found")

        return {"message": "Record deleted successfully", "record_id": record_id}

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e)) from e
