# /user/bin/env python3
# -*- coding: utf-8 -*-
"""Sample info class."""

import os
import re

import logging
import pandas as pd

from lc18report_dev.exceptions import InfoFileNotFoundError, MissingLabInfoFileError, MissingMergedInfoFileError, MissingSampleInfoFileError, SampleInfoFormatError

logger = logging.getLogger(__name__)


class Info:

    def __init__(self):
        self._sample_info_df: pd.DataFrame = pd.DataFrame()
        # self._sample_info_qido_df: pd.DataFrame = pd.DataFrame()
        self._lab_info_df: pd.DataFrame = pd.DataFrame()
        self._merged_info_df: pd.DataFrame = pd.DataFrame()

    def _set_sample_info_file(self, sample_info_file_prefix):
        sample_info_dir = os.path.dirname(sample_info_file_prefix)
        sample_info_prefix = os.path.basename(sample_info_file_prefix)
        all_files = sorted(os.listdir(sample_info_dir), reverse=True)
        for file in all_files:
            sample_info_file = os.path.join(sample_info_dir, file)
            if not os.path.isfile(sample_info_file):
                continue
            if file.startswith(sample_info_prefix):
                self._sample_info_df = pd.read_excel(
                    sample_info_file, sheet_name='项目信息表', dtype=str).fillna("")
                # self._sample_info_qido_df = pd.read_excel(
                #     sample_info_file, sheet_name='项目信息表-启东', dtype=str)
                return
        logger.error('Cannot find sample progress info file.')
        raise MissingSampleInfoFileError()

    def _set_lab_info_file(self, lab_info_file_prefix):
        lab_info_dir = os.path.dirname(lab_info_file_prefix)
        lab_info_prefix = os.path.basename(lab_info_file_prefix)
        for file in os.listdir(lab_info_dir):
            if not file.startswith(lab_info_prefix):
                continue
            lab_info_file = os.path.join(lab_info_dir, file)
            self._lab_info_df = pd.read_excel(
                lab_info_file, sheet_name='Sheet1', dtype=str).fillna("")
            lab_info_df3 = pd.read_excel(
                lab_info_file, sheet_name='Sheet3', dtype=str).fillna("")
            lab_info_df3['样本编号'] = lab_info_df3['样本编号'].str.replace(
                '^A', 'Lib', n=1)
            lab_info_df3['样本编号'] = lab_info_df3['样本编号'].str.replace(
                '^BD', 'Lib', n=1)
            self._lab_info_df = self._lab_info_df.merge(
                lab_info_df3, how='left',
                left_on='文库编号', right_on='样本编号')
            return
        logger.error('Cannot find sample progress info file.')
        raise MissingLabInfoFileError()

    def set_sample_lab_info_files(
            self, sample_info_file_prefix, lab_info_file_prefix):
        self._set_sample_info_file(sample_info_file_prefix)
        self._set_lab_info_file(lab_info_file_prefix)

    def set_merged_info_file(self, merged_info_file):
        if not os.path.isfile(merged_info_file):
            raise MissingMergedInfoFileError()
        merged_info_file = merged_info_file
        self._merged_info_df = pd.read_excel(merged_info_file, dtype=str)
        col_en2zh = {
            'SampleNo': '样本编号',
            'LibraryNo': '文库编号',
            'PatientName': '样本名称',
            'PatientSex': '性别',
            'PatientAge': '年龄',
            'ClinicalDiagnosis': '临床诊断',
            'PhysiologicalDiagnosis': '病理诊断',
            'PreviousTestResult': '既往基因检测结果',
            'TreatmentHistory': '治疗史',
            'SampleType': '样本类型',
            'SampleCollectionDate': '采集时间',
            'SampleReceiveDate': '收样日期',
            'TotalDnaAmount': 'DNA 总量',
            'TotalLibraryAmount': '文库总量',
            'BloodSampleVolume': '提取cfDNA血浆体积（mL）'
        }
        self._merged_info_df.rename(columns=col_en2zh)

    def _using_merged_info(self):
        return not self._merged_info_df.empty

    def _check_info(self):
        no_sample_info = self._sample_info_df is None
        no_lab_info = self._lab_info_df is None
        no_nonmerged_info = no_sample_info or no_lab_info
        no_merged_info = self._merged_info_df is None
        no_info = no_nonmerged_info and no_merged_info
        if no_info:
            raise InfoFileNotFoundError()

    def get_merged_info(self, head_values) -> pd.Series:
        merged_info_df = pd.DataFrame()
        for h, v in head_values:
            vnum = v
            vnum = re.sub("^[^0-9]*", "", vnum)
            vnum = re.sub("[^0-9]*$", "", vnum)
            merged_info_df = self._merged_info_df[
                self._merged_info_df[h].str.contains(vnum)]
            if not merged_info_df.empty:
                break
        first_value = head_values[0][1]
        if merged_info_df.empty:
            logger.error(f'[ERR]-({first_value}): Sample info not found.')
            return pd.Series()
        if len(merged_info_df.index) > 1:
            logger.error(
                f'({first_value}): Multiple sample info found')
            raise SampleInfoFormatError()
        merged_info = merged_info_df.iloc[0]
        return merged_info

    def get_sample_info(self, head_values) -> pd.Series:
        if self._using_merged_info():
            return self.get_merged_info(head_values)
        sample_info_df = pd.DataFrame()
        for h, v in head_values:
            # vnum = v
            # vnum = re.sub("^[^0-9]*", "", vnum)
            # vnum = re.sub("[^0-9]*$", "", vnum)
            sample_info_df = self._sample_info_df[
                self._sample_info_df[h] == v]
            if not sample_info_df.empty:
                break
        first_value = head_values[0][1]
        if sample_info_df.empty:
            logger.error(f'({first_value}): Sample info not found.')
            return pd.Series()
        if len(sample_info_df.index) > 1:
            logger.error(f'({first_value}): Multiple sample info found')
            raise SampleInfoFormatError()
        sample_info = sample_info_df.iloc[0]
        return sample_info

    def get_lab_info(self, head_values) -> pd.Series:
        if self._using_merged_info():
            return self.get_merged_info(head_values)
        lab_info_df = pd.DataFrame()
        for h, v in head_values:
            # vnum = v
            # vnum = re.sub("^[^0-9]*", "", vnum)
            # vnum = re.sub("[^0-9]*$", "", vnum)
            lab_info_df = self._lab_info_df[
                self._lab_info_df[h] == v]
            if not lab_info_df.empty:
                break
        first_value = head_values[0][1]
        if lab_info_df.empty:
            logger.error(f'[ERR]-({first_value}): Sample info not found.')
            return pd.Series()
        if len(lab_info_df.index) > 1:
            logger.error(
                f'({first_value}): Multiple sample info found')
            raise SampleInfoFormatError()
        lab_info = lab_info_df.iloc[0]
        return lab_info
