using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;

using FMSAdmin.Data;
using FMSAdmin.Helpers;
using FMSAdmin.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using FMSAdmin.Models;

namespace FMSApp.Services {
    public class DailyReportService {
        private readonly ILogger<DailyReportService> _logger;
        private readonly FMSContext _context;

        private readonly AppSettings _appSettings;
        private readonly StorageHelper _storage;

        public DailyReportService(
            ILogger<DailyReportService> logger,
            FMSContext context,
            IOptions<AppSettings> appSettings,
            StorageHelper storage
            ) {
            _logger = logger;
            _context = context;
            _appSettings = appSettings.Value;
            _storage = storage;
        }

        public IQueryable<FmsDailyReport> GetAll() {
            var query = _context.FmsDailyReport;
            return query;
        }

        public int GetWorkStatusByWorkTypeId(int siteId, int workTypeId, DateTime addDate) {
            return (from x in _context.FmsWorkOrder
                    let y = from y in _context.FmsWorkRequest
                            where y.SiteId == siteId &&             // 2019.07.12
                                    y.WorkTypeId == workTypeId
                            select y.WorkRequestId
                    where x.SiteId == siteId &&
                            x.OrderDate.Year == addDate.Year &&
                            x.OrderDate.Month == addDate.Month &&
                            x.OrderDate.Day == addDate.Day &&
                            y.Contains(x.WorkRequestId)
                    select x
            ).Count();
        }

        public int GetWorkStatusByWorkProgressId(int siteId, int workProgressId, DateTime addDate) {
            return (from x in _context.FmsWorkOrder
                    let y = from y in _context.FmsWorkRequest
                            where y.SiteId == siteId &&         //2019.07.12
                                    y.WorkProgressId == (int)workProgressId &&
                                    y.StartWorkDate <= addDate.Date
                            select y.WorkRequestId
                    where x.SiteId == siteId &&
                    y.Contains(x.WorkRequestId)
                    select x
            ).Count();
        }

        public int GetFmsWorkResultComplete(int siteId, int workProgressId, DateTime addDate) {
            return (from x in _context.FmsWorkResult
                    let y = from y in _context.FmsWorkRequest
                            where y.SiteId == siteId &&         //2019.07.12
                                    y.WorkProgressId == (int)workProgressId &&
                                    y.StartWorkDate <= addDate.Date
                            select y.WorkRequestId
                    where x.SiteId == siteId &&
                    y.Contains(x.WorkRequestId)
                    select x
            ).Count();
        }

        public int GetFmsWorkResultApproval(int siteId, int workProgressId, DateTime addDate) {
            return (from x in _context.FmsWorkResult
                    let y = from y in _context.FmsWorkRequest
                            where y.SiteId == siteId &&         //2019.07.12
                                    y.WorkProgressId == (int)workProgressId
                            select y.WorkRequestId
                    where x.SiteId == siteId &&
                    y.Contains(x.WorkRequestId) &&
                    x.ConfirmedDate.Value.Year == addDate.Year &&
                    x.ConfirmedDate.Value.Month == addDate.Month &&
                    x.ConfirmedDate.Value.Day == addDate.Day
                    select x
            ).Count();
        }

        public void Approve(int siteId, string approverUserId, DateTime addDate, int businessFieldId) {
            var persist = _context.FmsDailyReport.FirstOrDefault(
                x => x.SiteId == siteId
                && x.AddDate == addDate.Date
            // && x.BusinessFieldId == businessFieldId 20200625 요청
            );
            if (persist == null) throw new ServiceException("해당일자의 일간보고서가 존재하지 않습니다.");

            if (string.IsNullOrEmpty(persist.ApproverUserId)) {
                persist.ApproverUserId = approverUserId;
                persist.ApproveDate = DateTime.Now;
            } else if (string.IsNullOrEmpty(persist.ApproverUserId2)) {
                persist.ApproverUserId2 = approverUserId;
                persist.ApproveDate2 = DateTime.Now;
            } else if (string.IsNullOrEmpty(persist.ApproverUserId3)) {
                persist.ApproverUserId3 = approverUserId;
                persist.ApproveDate3 = DateTime.Now;
            } else if (string.IsNullOrEmpty(persist.ApproverUserId4)) {
                persist.ApproverUserId4 = approverUserId;
                persist.ApproveDate4 = DateTime.Now;
            } else if (string.IsNullOrEmpty(persist.ApproverUserId5)) {
                persist.ApproverUserId5 = approverUserId;
                persist.ApproveDate5 = DateTime.Now;
            } else {
                throw new ServiceException("결재 한도를 초과하였습니다.");
            }

            _context.FmsDailyReport.Update(persist);
            _context.SaveChanges();
        }


        public void Delete(int siteId, DateTime addDate, int businessFieldId) {
            var persist = _context.FmsDailyReport.FirstOrDefault(
                x => x.SiteId == siteId
                && x.AddDate == addDate.Date
                && x.BusinessFieldId == businessFieldId
            );
            if (persist == null) throw new ServiceException("해당일자의 일간보고서가 존재하지 않습니다.");

            _context.FmsDailyReport.Remove(persist);
            _context.SaveChanges();
        }

        public void Save(FmsDailyReport data, bool isCreate) {
            if (data.CmFile != null && data.CmFile.IsUpload) {
                data.CmFile.SiteId = data.SiteId;
                var category = _context.CmFileCategory.First(x => x.Name == "dailyReport");
                data.CmFile.FileCategory = category;
                data.CmFile.CreatedDate = DateTime.Now;
            } else {
                data.CmFile = null;
            }

            var persist = _context.FmsDailyReport.FirstOrDefault(
                x => x.SiteId == data.SiteId
                && x.AddDate == data.AddDate);
            if (persist == null) {
                data.RegisterDate = DateTime.Now;
                _context.FmsDailyReport.Add(data);
                _context.SaveChanges();
                if (data.CmFile != null && data.CmFile.IsUpload) {
                    _storage.CopyEntity(data.CmFile.Path, data.CmFile);
                }
            } else {
                if (isCreate) throw new ServiceException("해당일자의 보고서가 이미 등록되어있습니다.");

                persist.Name = data.Name;
                persist.Contents = data.Contents;
                persist.Datas = data.Datas;
                if (data.CmFile != null && data.CmFile.IsUpload) {
                    persist.CmFile = data.CmFile;
                }
                _context.FmsDailyReport.Update(persist);
                _context.SaveChanges();
                if (data.CmFile != null && data.CmFile.IsUpload) {
                    _storage.CopyEntity(data.CmFile.Path, persist.CmFile);
                }
            }

        }

        public void Delete(int siteId, DateTime addData) {
            try {
                var data = _context.FmsDailyReport.First(x => x.SiteId == siteId && x.AddDate == addData);
                _context.FmsDailyReport.Remove(data);
                //data.IsUse = false;
                _context.SaveChanges();
            } catch {
                throw new ServiceException("이미 다른 화면에서 사용중이므로 삭제할 수 없습니다.");
            }
        }
    }
}