import json
import logging
import time
from datetime import date, datetime
from io import BytesIO
from typing import Optional

from django.conf import settings
from django.db import models
from pandas.tseries.offsets import BDay
from wbcore.contrib.io.backends import AbstractDataBackend, register

from wbportfolio.api_clients.jpm import JPMNexusAPIClient

from ..mixin import BankDataBackendMixin

logger = logging.getLogger("io")


@register("Fees", provider_key="jpm", save_data_in_import_source=True, passive_only=True)
class DataBackend(BankDataBackendMixin, AbstractDataBackend):
    PRODUCT_IDENTIFIER = "ticker"

    def __init__(
        self, import_credential: Optional[models.Model] = None, bank: Optional[models.Model] = None, **kwargs
    ):
        if not bank:
            raise ValueError("The jpm company objects needs to be passed to this backend")
        self.bank = bank

    def get_files(
        self,
        execution_time: datetime,
        start: date = None,
        obj_external_ids: list[str] = None,
        **kwargs,
    ) -> BytesIO:
        execution_date = (execution_time - BDay(1)).date()
        if obj_external_ids:
            # we don't expect these credentials to change, so it is fine to directly use the config. Otherwise, use a the attribute import_credential
            client = JPMNexusAPIClient(settings.JPM_NEXUS_API_CLIENT_ID, settings.JPM_NEXUS_API_CLIENT_SECRET)
            errors = []
            for external_id in obj_external_ids:
                try:
                    res_json = client.validate_response(client.get_amc_report("fee", external_id, execution_date)).get(
                        "result", [[]]
                    )[0]  # we expect result to be a 2D list
                    time.sleep(1)
                    if res_json:
                        content_file = BytesIO()
                        content_file.write(json.dumps(res_json).encode())
                        file_name = f"jpm_fees_{external_id}_{execution_date:%Y-%m-%d}_{datetime.timestamp(execution_time)}.json"
                        yield file_name, content_file
                except Exception:
                    errors.append(external_id)
            if errors:
                logger.error(f"Couldn't import data for {errors}")
