using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;

using CSVDownloader.Code;
using CSVDownloader.Store.CreditCSVData;
using CSVDownloader.Exceptions;

using ExpectedConditions = OpenQA.Selenium.Support.UI.ExpectedConditions;

namespace CSVDownloader.Web {
    class ItecController : WebController {

        private readonly String url_ = "https://www.itc-offerinfo.net/webap/Login";

        private enum XpathKey {
            INPUT_LOGIN_USERNAME,
            INPUT_LOGIN_PASSWORD,
            BUTTON_LOGIN,
            BUTTON_CREDIT_KESSAI,
            RADIO_TARGET_SPAN,
            SELECT_TARGET_FROM_YYYYMM,
            SELECT_TARGET_FROM_DD,
            SELECT_TARGET_TO_YYYYMM,
            SELECT_TARGET_TO_DD,
            BUTTON_CONFIRM_CSV,
            BUTTON_DOWNLOAD_CSV,
            BUTTON_LOGOUT,
        };

        private IDictionary<XpathKey, string> xpath_map_ = new Dictionary<XpathKey, string>()
        {
             {XpathKey.INPUT_LOGIN_USERNAME,@"//*[@id='panel']/div[2]/input" },
             {XpathKey.INPUT_LOGIN_PASSWORD,@"//*[@id='panel']/div[4]/input"},
             {XpathKey.BUTTON_LOGIN,@"//*[@id='area_m']/form/div[2]/input[1]"},
             {XpathKey.BUTTON_CREDIT_KESSAI,@"//*[@id='menuRa']" },
             {XpathKey.RADIO_TARGET_SPAN,@"//*[@id='kikantype1']" },
             {XpathKey.SELECT_TARGET_FROM_YYYYMM,$"//*[@id='kikan_from_month']" },
             {XpathKey.SELECT_TARGET_FROM_DD,$"//*[@id='kikan_from_day']" },
             {XpathKey.SELECT_TARGET_TO_YYYYMM,$"//*[@id='kikan_to_month']" },
             {XpathKey.SELECT_TARGET_TO_DD,$"//*[@id='kikan_to_day']" },
             {XpathKey.BUTTON_CONFIRM_CSV,$"//*[@id='btn-exec']" },
             {XpathKey.BUTTON_DOWNLOAD_CSV,$"//*[@id='dl-detail']" },
             {XpathKey.BUTTON_LOGOUT,$"//*[@id='btn_logout']" },
         };


        public ItecController(ChromeDriver driver) : base(driver) {
            agent_ = CreditAgent.ITEC;
        }

        public override void SetParkingDic(IDictionary<String, String> dic) {

            dic_ = new Dictionary<String, String>();
            // IPコードと駐車場名を分離。プログラムではIPコードのみ利用する。
            foreach (var ele in dic) {
                String parking_name = ele.Key.Split(" ")[0].Trim();
                dic_.Add(parking_name, ele.Value);
            }
        }

        public override ResultCode Login(LoginInfo info) {

            try {
                driver_.Navigate().GoToUrl(url_);
                Send(xpath_map_[XpathKey.INPUT_LOGIN_USERNAME], info.user_name);
                Send(xpath_map_[XpathKey.INPUT_LOGIN_PASSWORD], info.password);

                Click(xpath_map_[XpathKey.BUTTON_LOGIN]);

                // ログイン後の明細データダウンロードが表示されることを確認する。
                wait_.Until(ExpectedConditions.ElementToBeClickable(By.XPath(xpath_map_[XpathKey.BUTTON_CREDIT_KESSAI])));

            } catch (Exception e) {
                logger_.Error(e.Message);
                return ResultCode.NG;
            }
            return ResultCode.OK;
        }

        public override ResultCode Download(DateTime from, DateTime to) {
            // クレジットカード承認結果一覧画面に移行
            Click(xpath_map_[XpathKey.BUTTON_CREDIT_KESSAI]);

            // 承認処理日のFrom-Toを入力
            Select(xpath_map_[XpathKey.SELECT_TARGET_FROM_YYYYMM], from.ToString("yyyyMM"));
            Select(xpath_map_[XpathKey.SELECT_TARGET_FROM_DD], from.ToString("dd"));
            Select(xpath_map_[XpathKey.SELECT_TARGET_TO_YYYYMM], to.ToString("yyyyMM"));
            Select(xpath_map_[XpathKey.SELECT_TARGET_TO_DD], to.ToString("dd"));

            // 各種ラジオチェックを入力
            Click(xpath_map_[XpathKey.RADIO_TARGET_SPAN]);


            // 条件確定
            Click(xpath_map_[XpathKey.BUTTON_CONFIRM_CSV]);

            // ダウンロード開始
            Click(xpath_map_[XpathKey.BUTTON_DOWNLOAD_CSV]);
            String filename = $"itec.csv";
            WaitForDownload(filename);


            return ResultCode.OK;
        }

        public override ResultCode Logout() {


            Click(xpath_map_[XpathKey.BUTTON_LOGOUT]);

            return ResultCode.OK;
        }


        public override List<CreditCSVData> GetCreditCSVDataList() {

            var result_list = new List<CreditCSVData>();


            // csvファイルパスの取得
            var config = new CSVConfig() {
                header = true,
            };

            var dir = new DirectoryInfo(DriverFactory.GetDownloadDir());

            var sjis_enc = Encoding.GetEncoding("Shift-JIS");
            var list = new List<String[]>();
            foreach (var file in dir.GetFiles()) {
                var result = ReadCsv(file.FullName, config, sjis_enc);
                list.AddRange(result);
            }

            bool failed_flg = false;
            var failed_parking_name_hs_table = new HashSet<String>();

            foreach (var line in list) {


                // 空の行はスキップする
                if (line.Length == 0) {
                    continue;
                }

                // 不要な行はスキップする
                if (line.Length != 10) {
                    continue;
                }

                var parking_name = line[(int)CreditCSVDataItec.ColName.ParkingName];


                try {
                    result_list.Add(new CreditCSVDataItec() {
                        spot_id = GetSpotID(parking_name),
                        code = line[(int)CreditCSVDataItec.ColName.Code],
                        parking_name = parking_name,
                        device_type = line[(int)CreditCSVDataItec.ColName.DeviceType],
                        use_datetime = DateTime.Parse(line[(int)CreditCSVDataItec.ColName.UseDatetime]),
                        trade = line[(int)CreditCSVDataItec.ColName.Trade],
                        card_company_name = line[(int)CreditCSVDataItec.ColName.CardCompanyName],
                        amount = int.Parse(line[(int)CreditCSVDataItec.ColName.Amount]),
                        tax_send_fee = int.Parse(line[(int)CreditCSVDataItec.ColName.TaxSendFee]),
                        total_amount = int.Parse(line[(int)CreditCSVDataItec.ColName.TotalAmount]),
                        error_code = line[(int)CreditCSVDataItec.ColName.ErrorCode],
                    });

                } catch (ArgumentException) {
                    failed_parking_name_hs_table.Add(parking_name);
                    failed_flg = true;
                    continue;
                }
            }

            if (failed_flg) {
                if (failed_flg) {
                    var error_list = new List<Store.ParkingCreditCardAgenciesSpotIDError>();
                    logger_.Error("失敗駐車場名");
                    foreach (var ele in failed_parking_name_hs_table) {
                        error_list.Add(new Store.ParkingCreditCardAgenciesSpotIDError() {
                            creditcard_agencies_id = CreditAgenciesMap.GetID(agent_),
                            creditcard_agencies_spot_name = ele
                        });
                        logger_.Error($"駐車場 \"{ele}\"");
                    }

                    throw new SpotNameNotMatchException(error_list);
                }

            }

            return result_list;
        }
    }
}
