using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json.Linq;

namespace JtkManagerClient {
    public partial class SalesForm : Form {
        private CancellationTokenSource inqueryCancellationTokenSource;

        public SalesForm() {
            InitializeComponent();
            AcceptButton = null;
            CancelButton = null;
        }

        private void SalesForm_Load(object sender, EventArgs e) {
            var now = DateTime.Now;
            this.fromDatePicker.Value = DateTime.Parse($"{now.Year:0000}-{now.Month:00}-01");
            inqueryButton_Click(inqueryButton, EventArgs.Empty);

            var scale = CreateGraphics().DpiX / 96f;
            foreach (ColumnHeader col in listView.Columns) {
                col.Width = (int)(col.Width * scale);
            }

            //graphView.XAxisConverter += d => $"{d/10000:0000}-{(d-d/10000)/100:00}-{(d-d/100):00}";
            graphView.XAxisConverter += d => {
                var year = (int)Math.Floor(d / 10000);
                var month = (int)Math.Floor((d / 10000 - (int)(d / 10000)) * 100);
                var day = (int)((d / 100 - (int)(d / 100)) * 100);
                while (DateTime.DaysInMonth(year, month) < day) {
                    day -= DateTime.DaysInMonth(year, month);
                    if (++month > 12) {
                        year++;
                    }
                }
                return $"{month:00}/{day:00}";
            }; 
        }

        private async void inqueryButton_Click(object sender, EventArgs e) {
            using (inqueryCancellationTokenSource = new CancellationTokenSource()) {
                await Inquery(inqueryCancellationTokenSource.Token);
            }
            inqueryCancellationTokenSource = null;
        }

        private Task Inquery(CancellationToken cancellationToken = default) {
            if (cancellationToken == default) {
                cancellationToken = CancellationToken.None;
            }
            inqueryButton.Enabled = false;
            periodGroupBox.Enabled = false;
            this.Cursor = Cursors.AppStarting;
            return Task.Factory.StartNew(state => {
                var token = (CancellationToken)state;

                var fromTime = DateTime.Parse($"{fromDatePicker.Value.Year:0000}-{fromDatePicker.Value.Month:00}-{fromDatePicker.Value.Day:00} 00:00:00");
                var toTime = DateTime.Parse($"{toDatePicker.Value.Year:0000}-{toDatePicker.Value.Month:00}-{toDatePicker.Value.Day:00} 23:59:59");
                var days = (int)((toTime - fromTime).TotalDays) + 1;

                var task = Program.GetPostResponseAsync(JObject.FromObject( new { work="get_sales", from=fromTime, to=toTime }));
                task.Wait(/*token*/);
                var response = task.Result;
                if (token.IsCancellationRequested == false) {
                    this.Invoke(new Action(() => {
                        Cursor = Cursors.Default;
                        inqueryButton.Enabled = true;
                        periodGroupBox.Enabled = true;

                        if (response == null || response["result"].ToString() == "error") {
                            this.Invoke(new Action(() => MessageBox.Show("실패!")));
                            return;
                        }

                        listView.Items.Clear();
                        var graphData = new List<(double x, double y, string text)>();
                        var totalSale = 0.0;
                        var totalVisit = 0;

                        foreach (var item in response["list"]) {
                            var userId = item["user_id"].ToString();
                            var loggedInTime = item["logged_in_time"].ToObject<DateTime>();
                            var loggedOutTime = item["logged_out_time"].ToObject<DateTime>();
                            var cash = item["cash"].ToObject<double>();
                            var usedTime = loggedOutTime - loggedInTime;
                            string usedTimeString;
                            if (usedTime.TotalHours >= 1.0) {
                                usedTimeString = $"{Math.Floor(usedTime.TotalHours)}시간 {usedTime.Minutes}분";
                            } else if (usedTime.TotalMinutes >= 1.0) {
                                usedTimeString = $"{usedTime.Minutes}분";
                            } else {
                                usedTimeString = $"{usedTime.Seconds}초";
                            }
                            listView.Items.Add(new ListViewItem(new string[] {
                                loggedInTime.ToString("yyyy-MM-dd HH:mm:ss"),
                                userId,
                                usedTimeString,
                                "￦" + cash.ToString("N0")
                            }));
                            var doubleDate = loggedInTime.Year * 10000.0 + loggedInTime.Month * 100.0 + loggedInTime.Day;

                            var found = false;
                            for (var i = 0; i < graphData.Count; i++) {
                                if (graphData[i].x == doubleDate) {
                                    graphData[i] = (doubleDate, graphData[i].y + cash, $"{loggedInTime.ToString("MM/dd")}\r\n￦{(graphData[i].y + cash):N0}");
                                    found = true;
                                    break;
                                }
                            }
                            if (found == false) {
                                graphData.Add((doubleDate, (float)cash, $"{loggedInTime.ToString("MM/dd")}\r\n￦{(cash):N0}"));
                            }

                            totalVisit++;
                            totalSale += cash;
                        }
                        
                        var data = new Dictionary<Color, (double x, double y, string text)[]>();
                        data[Color.Red] = graphData.ToArray();
                        graphView.XAxisMin = double.Parse(fromTime.ToString("yyyyMMdd"));
                        graphView.XAxisMax = graphView.XAxisMin + days;
                        graphView.YAxisMin = 0f;
                       // graphView.XAxisUnit = 1f;
                        graphView.Data = data;

                        visitCountLabel.Text = $"총 방문 수: {totalVisit:N0}회 (일 평균 {(float)totalVisit/days:N1}회)";
                        salesLabel.Text = $"매출: ￦{totalSale:N0} (일 평균 ￦{totalSale/days:N1})";
                    }));
                    
                }
            }, cancellationToken, cancellationToken);
        }

        private void SalesForm_FormClosed(object sender, FormClosedEventArgs e) {
            inqueryCancellationTokenSource?.Cancel();
        }
    }
}
