"A call to get data from the SEC. Don't use the SEC-API, it's not free. Use the EDGAR API instead."
import json
import time
from typing import Literal

import requests


def rate_limit(func):
    def wrapper(*args, **kwargs):
        # get the time difference between the last request and now
        time_diff = time.time() - args[0].last_request_time
        # get the time difference in seconds
        rate_limit_per_second = args[0].rate_limit_per_second
        # get the time to sleep
        time_to_sleep = (1 / rate_limit_per_second) - time_diff
        if time_to_sleep > 0:
            time.sleep(time_to_sleep)

        response = func(*args, **kwargs)
        # update the last request time
        args[0].last_request_time = time.time()
        return response

    return wrapper


class SECReports:
    "A class to get reports from the EDGAR API"
    headers = {
        "User-Agent": "X Cap Market sagar.soni@xcapmarket.com",
    }
    # set the last request time
    last_request_time = time.time()
    rate_limit_per_second = 10

    def __init__(
        self,
        ticker: str,
        filing_type: Literal["10-K", "10-Q", "8-K"],
        last_n_reports: int = 1,
    ):
        self.ticker = ticker
        self.filing_type = filing_type
        self.last_n_reports = last_n_reports

        self.cik = self.convert_ticker_to_cik(ticker)
        self.reports_info = self.get_reports(self.cik)

        self.sic_code = self.reports_info["sic"]
        self.fiscal_year_end = self.reports_info["fiscalYearEnd"]

        self.filings = self.reports_info["filings"]["recent"]

        self.reports = self.get_reports_accession_numbers()

    @rate_limit
    def convert_ticker_to_cik(self, ticker):
        "Converts a ticker to a CIK number"
        url = f"https://www.sec.gov/cgi-bin/browse-edgar?CIK={ticker}&owner=exclude&action=getcompany"
        response = requests.get(url, headers=self.headers, timeout=5)
        cik = response.text.split("CIK=")[1].split("&amp")[0]
        return cik

    @rate_limit
    def get_reports(self, cik: str = None):
        "Get the reports from the SEC"
        if cik is None and self.cik is None:
            raise ValueError("CIK is not provided")

        url = f"https://data.sec.gov/submissions/CIK{cik}.json"
        response = requests.get(url, headers=self.headers, timeout=5)
        return response.json()

    @rate_limit
    def get_reports_accession_numbers(self):
        "Get the accession numbers of the reports"
        report_index = []
        for i, primary_doc_dsc in enumerate(self.filings["primaryDocDescription"]):
            if (
                self.filing_type in primary_doc_dsc
                and len(report_index) < self.last_n_reports
            ):
                report_index.append(i)

        reports = []
        for i in report_index:
            reports.append(
                {
                    "accessionNumber": self.filings["accessionNumber"][i].replace(
                        "-", ""
                    ),
                    "filingDate": self.filings["filingDate"][i],
                    "primaryDocument": self.filings["primaryDocument"][i],
                    "fileNumber": self.filings["fileNumber"][i],
                    "report_date": self.filings["reportDate"][i],
                    "report_main_doc": self.get_specific_report(
                        self.filings["accessionNumber"][i].replace("-", ""),
                        self.filings["primaryDocument"][i],
                    ),
                    "report_text": self.get_specific_report(
                        self.filings["accessionNumber"][i].replace("-", ""),
                        self.filings["accessionNumber"][i] + ".txt",
                    ),
                    "exhibits": self.get_exhibits(
                        self.filings["accessionNumber"][i].replace("-", "")
                    ),
                }
            )
        return reports

    @rate_limit
    def get_specific_report(self, accession_number: str, primary_document: str):
        "Get the reports from the SEC"
        url = f"https://www.sec.gov/Archives/edgar/data/{self.cik}/{accession_number}/{primary_document}"
        response = requests.get(url, headers=self.headers, timeout=5)
        return response.text

    @rate_limit
    def get_exhibits(self, accession_number: str):
        "Get the exhibits from the SEC"
        url = f"https://www.sec.gov/Archives/edgar/data/{self.cik}/{accession_number}/index.json"
        response = requests.get(url, headers=self.headers, timeout=5)
        # loop through the response to get the exhibits
        exhibits = []
        for file in response.json()["directory"]["item"]:
            if "ex99" in file["name"]:
                url = f"https://www.sec.gov/Archives/edgar/data/{self.cik}/{accession_number}/{file['name']}"
                response = requests.get(url, headers=self.headers, timeout=5)
                exhibits.append({"name": file["name"], "text": response.text})
        return exhibits


if __name__ == "__main__":

    ticker = "AAPL"
    filing_type = "10-K"
    n_reports = 1
    sec = SECReports(ticker, filing_type, n_reports)
    # write the text file to a html
    with open("report.html", "w") as f:
        f.write(sec.reports[0]["report_main_doc"])
