import json
from collections import OrderedDict
from datetime import datetime
from typing import Optional

from pydantic import BaseModel

from src.model.db.pharmacy_product_master import PharmacyProductMasterModel
from src.model.db.wholesaler_master import WholesalerMasterModel
from src.model.request.bio import BioModel
from src.model.view.bio_disp_model import BisDisplayModel
from src.system_var import environment


class BioViewModel(BaseModel):
    subtitle: str = '生物由来検索一覧'
    user_id: Optional[str]
    batch_status: Optional[str]
    whs_models: list[WholesalerMasterModel]
    phm_models: list[PharmacyProductMasterModel]
    bio_data: Optional[list[BisDisplayModel]] = []
    form_data: Optional[BioModel]

    def display_wholesaler_names(self):
        display_names = [
            f'{whs_model.rec_whs_cd}-{whs_model.rec_whs_sub_cd}:{whs_model.name}'
            for whs_model in self.whs_models
        ]
        return display_names

    def display_org_kbn(self):
        return OrderedDict(
            {
                '': '',
                'J': 'JD-NET',
                'N': 'NHI',
                'H': '手入力'
            }
        )

    def display_data_kbn(self):
        return OrderedDict(
            {
                '': '',
                '0': '正常',
                '1': 'ロットエラー',
                '3': 'ロット不明',
                '9': 'エラー（解消済）',
                '2': '除外'
            }
        )

    def bio_data_json_str(self):
        def date_handler(obj):
            return obj.isoformat() if hasattr(obj, 'isoformat') else obj
        return json.dumps([model.dict() for model in self.bio_data], ensure_ascii=False, default=date_handler)

    def is_selected_whs_name(self, selected_wholesaler):
        if not self.is_form_submitted():
            return ''

        form_wholesaler_full_name = \
            f'{self.form_data.rec_whs_cd}-{self.form_data.rec_whs_sub_cd}:{self.form_data.whs_name}'

        return self._selected_value(form_wholesaler_full_name, selected_wholesaler)

    def is_selected_org_kbn(self, selected_org_kbn):
        if not self.is_form_submitted():
            return ''
        return self._selected_value(self.form_data.slip_org_kbn, selected_org_kbn)

    def is_input_rec_ymd_from(self):
        if not self.is_form_submitted():
            return ''

        return self._format_date_string(self.form_data.rec_ymd_from)

    def is_input_rec_ymd_to(self):
        if not self.is_form_submitted():
            return ''

        return self._format_date_string(self.form_data.rec_ymd_to)

    def is_input_lot_num(self):
        if not self.is_form_submitted():
            return ''

        return self.form_data.rec_lot_num or ''

    def is_selected_data_kbn(self, selected_data_kbn):
        if not self.is_form_submitted():
            return ''

        return self._selected_value(self.form_data.data_kbn, selected_data_kbn)

    def is_selected_maker_cd(self, selected_maker_cd):
        if not self.is_form_submitted():
            return ''

        return self._selected_value(self.form_data.mkr_cd, selected_maker_cd)

    def is_input_rev_hsdnymd_srk_from(self):
        if not self.is_form_submitted():
            return ''

        return self._format_date_string(self.form_data.rev_hsdnymd_srk_from)

    def is_input_rev_hsdnymd_srk_to(self):
        if not self.is_form_submitted():
            return ''

        return self._format_date_string(self.form_data.rev_hsdnymd_srk_to)

    def is_checked_iko_flg(self):
        if not self.is_form_submitted():
            return ''

        return 'checked' if self.form_data.iko_flg else ''

    def disabled_button(self):
        return 'disabled' if self.is_data_empty() or self.is_data_overflow_max_length() else ''

    def is_form_submitted(self):
        return self.form_data is not None

    def is_data_empty(self):
        return len(self.bio_data) == 0

    def is_data_overflow_max_length(self):
        return len(self.bio_data) > environment.BIO_SEARCH_RESULT_MAX_COUNT

    def _format_date_string(self, date_string):
        if date_string is None:
            return ''
        date = datetime.strptime(date_string, '%Y%m%d')
        return date.strftime('%Y/%m/%d')

    def _selected_value(self, form_value: str, current_value: str):
        return 'selected' if form_value == current_value else ''
