"Class to store company details"
import datetime
import socket
from decimal import Decimal
from typing import List

from pydantic import BaseModel, field_validator
from sqlalchemy import TIMESTAMP, Column, Integer, String
from sqlalchemy.sql import func

from app.services.company_profile.data_classes.llm_results import LLMQuery
from app.utils.dynamo_db import DynamoDB
from app.utils.mysql_db import Base
from app.utils.url_parser import parsed_url


class Images(BaseModel):
    "Class to store image details"
    count: int
    src: str
    type: str

    @field_validator("count", mode="before")
    @classmethod
    def create_count(cls, raw_count):
        "convert the count to int"
        return int(raw_count)


class Logo(BaseModel, extra="allow"):
    "Class to store logo details"
    logo_extension: int
    logo_url: str
    logo_dark: bool | None = None
    logo_format: str | None = None


class CompanyInfo(BaseModel):
    "Class to store company details"
    root_url: str
    company_name: str
    images: List[Images] | None = None

    linkedin: List[str] | None = []
    logo: Logo | None = None

    business_model: bool | None = None
    industry: str | None = None
    sector: str | None = None
    stock_exchange: str | None = None
    stock_ticker: str | None = None

    created_by: str | None = socket.gethostname()
    created_date: str | None = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    modified_by: str | None = socket.gethostname()
    modified_date: str | None = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    @field_validator("images", mode="before")
    @classmethod
    def create_images(cls, raw_images: list):
        "convert the list of images to the Images class"
        if raw_images is None:
            return None
        elif len(raw_images) == 0:
            return None

        images_list = []
        for image in raw_images:
            images_list.append(Images(**image))

        return images_list

    @field_validator("logo", mode="before")
    @classmethod
    def create_logo(cls, raw_logo: dict):
        "convert the list of images to the Images class"
        if isinstance(raw_logo, Logo):
            return raw_logo

        if raw_logo is False:
            return Logo(logo_dark=True, logo_extension=0, logo_url="")
        elif raw_logo is None:
            return None
        elif len(raw_logo) == 0:
            return None

        return Logo(**raw_logo)

    @field_validator("linkedin", mode="before")
    @classmethod
    def create_linkedin(cls, raw_linkedin):
        "convert the raw linkedin into the accepted input"
        if isinstance(raw_linkedin, list):
            return flatten_list(raw_linkedin)
        elif isinstance(raw_linkedin, str) == str:
            return [raw_linkedin]

    @field_validator("company_name", mode="before")
    @classmethod
    def create_company_name(cls, raw_company_name, raw_root_url):
        "convert the company name to the accepted input"
        if raw_company_name is None:
            raw_root_url = raw_root_url.data["root_url"]
            return raw_root_url.split("www.")[-1].split(".")[0].capitalize()
        return raw_company_name

    def update_modify(self):
        "Update the modified date and modified by"
        self.modified_by = socket.gethostname()
        self.modified_date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    @staticmethod
    def get_company_info(company_url):
        "Get company info from the database"
        company_url = parsed_url(company_url).url
        db = DynamoDB()

        company_info_data = db.get_item(db.company_info_table, company_url)

        if company_info_data is None:
            raise ValueError(f"{company_url} not found in the database.")

        return CompanyInfo(**company_info_data)


def flatten_list(nested_list):
    flattened = []
    for item in nested_list:
        if isinstance(item, list):
            flattened.extend(flatten_list(item))
        else:
            flattened.append(item)
    return flattened


class FundInfo(BaseModel):
    "Class to store company details"
    root_url: str
    company_name: str
    images: List[Images] | None = None

    linkedin: List[str] | None = []
    logo: Logo | None = None

    business_model: bool | None = None
    industry: str | None = None
    sector: str | None = None
    stock_exchange: str | None = None
    stock_ticker: str | None = None

    created_by: str | None = socket.gethostname()
    created_date: str | None = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    modified_by: str | None = socket.gethostname()
    modified_date: str | None = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    LLM_results: list[LLMQuery] | None = None

    @field_validator("images", mode="before")
    @classmethod
    def create_images(cls, raw_images: list):
        "convert the list of images to the Images class"
        if raw_images is None:
            return None
        elif len(raw_images) == 0:
            return None

        images_list = []
        for image in raw_images:
            images_list.append(Images(**image))

        return images_list

    @field_validator("logo", mode="before")
    @classmethod
    def create_logo(cls, raw_logo: dict):
        "convert the list of images to the Images class"
        if isinstance(raw_logo, Logo):
            return raw_logo

        if raw_logo is False:
            return Logo(logo_dark=True, logo_extension=0, logo_url="")
        elif raw_logo is None:
            return None
        elif len(raw_logo) == 0:
            return None

        return Logo(**raw_logo)

    @field_validator("linkedin", mode="before")
    @classmethod
    def create_linkedin(cls, raw_linkedin):
        "convert the raw linkedin into the accepted input"
        if isinstance(raw_linkedin, list):
            return raw_linkedin
        elif isinstance(raw_linkedin, str) == str:
            return [raw_linkedin]

    @field_validator("company_name", mode="before")
    @classmethod
    def create_company_name(cls, raw_company_name, raw_root_url):
        "convert the company name to the accepted input"
        if raw_company_name is None:
            raw_root_url = raw_root_url.data["root_url"]
            return raw_root_url.split("www.")[-1].split(".")[0].capitalize()
        return raw_company_name

    def update_modify(self):
        "Update the modified date and modified by"
        self.modified_by = socket.gethostname()
        self.modified_date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    @staticmethod
    def get_company_info(company_url):
        "Get company info from the database"
        company_url = parsed_url(company_url).url
        db = DynamoDB()
        company_info_data = db.get_item(db.company_info_table, company_url)

        if company_info_data is None:
            raise ValueError(f"{company_url} not found in the database.")

        return CompanyInfo(**company_info_data)


class CompanyInfoModelSql(Base):
    "MySQL table for company information"
    __tablename__ = "company_info"
    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    root_url = Column(String(255), unique=True, nullable=False)
    company_name = Column(String(255), nullable=False)
    ticker = Column(String(50), nullable=True)
    created_at = Column(TIMESTAMP, server_default=func.now())
    updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now())

    @classmethod
    def search_filters(cls, search_term: str):
        """
        Generate filters and order_by for searching company info.
        """
        filters = [
            (cls.company_name.like(f"%{search_term}%"))
            | (cls.root_url.like(f"%{search_term}%"))
            | (cls.ticker.like(f"%{search_term}%"))
        ]
        order_by = [cls.company_name.like(f"%{search_term}%").desc()]
        return filters, order_by

    def to_dict(self):
        "Convert the class to a dictionary"
        return {
            "id": self.id,
            "root_url": self.root_url,
            "company_name": self.company_name,
            "ticker": self.ticker,
        }


class FundInfoModelSql(Base):
    "MySQL table for fund information"
    __tablename__ = "fund_info"
    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    root_url = Column(String(255), unique=True, nullable=False)
    company_name = Column(String(255), nullable=False)
    created_at = Column(TIMESTAMP, server_default=func.now())
    updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now())

    @classmethod
    def search_filters(cls, search_term: str):
        """
        Generate filters and order_by for searching company info.
        """
        filters = [
            (cls.company_name.like(f"%{search_term}%"))
            | (cls.root_url.like(f"%{search_term}%"))
        ]
        order_by = [cls.company_name.like(f"%{search_term}%").desc()]
        return filters, order_by

    def to_dict(self):
        "Convert the class to a dictionary"
        return {
            "id": self.id,
            "root_url": self.root_url,
            "company_name": self.company_name,
        }


if __name__ == "__main__":

    comp_dict = {
        "stock_ticker": "U",
        "root_url": "https://www.unity.com",
        "modified_date": "2024-02-13 12:45:32",
        "linkedin": [
            "https://www.linkedin.com/in/anirmagupta/",
            "https://www.linkedin.com/in/jessica-lindl-8b73a5/",
            "https://www.linkedin.com/in/luis-felipe-visoso-aa841a22/",
            "https://www.linkedin.com/in/scott-pitasky-4999891/",
            "https://www.linkedin.com/company/unity/life/inclusion/",
            "https://www.linkedin.com/in/katie-stocks/",
            "https://www.linkedin.com/company/unity-technologies",
            "https://www.linkedin.com/in/tomerbarzeev/",
            "https://www.linkedin.com/in/carolwcarpenter/",
            "https://www.linkedin.com/company/unity-technologies/life/inclusion/",
            "https://www.linkedin.com/in/lualmayen/",
            "https://www.linkedin.com/in/thomas-winkley-783b4713/",
            "https://www.linkedin.com/in/clive-downie-2003b07/",
            "https://www.linkedin.com/in/lucbarthelet/",
            "https://www.linkedin.com/in/oleg-sysoev-4b11122b/",
            "https://www.linkedin.com/in/marcwhitten/",
            "https://linkedin.com/company/unity",
        ],
        "sector": "Services-Prepackaged Software",
        "created_by": "Sagar-Asus",
        "created_date": "2023-12-29 20:56:14",
        "industry": "Technology",
        "stock_exchange": None,
        "modified_by": "ip-172-31-27-207",
        "logo": {
            "logo_dark": True,
            "logo_url": "https://asset.brandfetch.io/idEc0EPR9J/idlfYmkSwj.svg",
            "logo_extension": Decimal("1"),
        },
        "name": "Unity",
        "company_name": "Unity",
        "scrapped": True,
        "images": [
            {
                "count": Decimal("1000"),
                "type": "img",
                "src": "https://cdn.langeek.co/photo/26028/original/none",
            },
            {
                "count": Decimal("1000"),
                "type": "img",
                "src": "https://as2.ftcdn.net/v2/jpg/00/73/00/39/500_F_73003953_DVFZYwH4iXxOlsNSVqljeqkNBg6xIUDM.jpg",
            },
            {
                "count": Decimal("1000"),
                "type": "img",
                "src": "https://merriam-webster.com/assets/mw/images/video/vid-video-play-lg/is-none-singular-or-plural-video-1753-06bba640fa47b87641138f8d2f0e600b@1x.jpg",
            },
            {
                "count": Decimal("1000"),
                "type": "img",
                "src": "https://play-lh.googleusercontent.com/LECOTVlGWVclV1VU3-1YcNoQdF2f37jQaQhX353GkySuwK9EcPXgy92YgKB3QeNvZMXe",
            },
            {
                "count": Decimal("1000"),
                "type": "img",
                "src": "https://i0.wp.com/www.affordableeditingservices.com/wp-content/uploads/2016/08/None.jpg",
            },
            {
                "count": Decimal("1000"),
                "type": "img",
                "src": "https://i.ytimg.com/vi/UH9uKJkkhZA/sddefault.jpg",
            },
            {
                "count": Decimal("1000"),
                "type": "img",
                "src": "https://i.ytimg.com/vi/tnHbeCHApOw/maxresdefault.jpg",
            },
            {
                "count": Decimal("1000"),
                "type": "img",
                "src": "https://www.shutterstock.com/shutterstock/photos/1504674191/display_1500/stock-vector-none-vector-hand-drawn-illustration-with-cartoon-lettering-good-as-a-sticker-video-blog-cover-1504674191.jpg",
            },
            {
                "count": Decimal("1000"),
                "type": "img",
                "src": "https://steamcdn-a.akamaihd.net/steam/apps/398970/header.jpg",
            },
            {
                "count": Decimal("1000"),
                "type": "img",
                "src": "https://cdn.langeek.co/photo/19923/original/none-vs-non",
            },
        ],
        "business_model": None,
        "modified_Date": "2024-02-02 23:35:05",
    }

    company_info = CompanyInfo(**comp_dict)

    print(company_info.model_dump())
