using Castle.Core.Internal;
using ClosedXML.Excel;
using DocumentFormat.OpenXml.Drawing;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml.Wordprocessing;
using Infrastructure;
using Infrastructure.Extensions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NUnit.Framework.Internal.Execution;
using OpenAuth.App.Interface;
using OpenAuth.Repository;
using OpenAuth.Repository.Domain;
using SqlSugar;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Nodes;
using System.Threading.Tasks;

namespace OpenAuth.App
{
    public class BasicTableService
    {

        ISqlSugarClient client;

        IAuth auth;
        
        public BasicTableService(ISqlSugarClient client,IAuth auth)
        {
            this.client = client;
            this.auth = auth;
        }

        /// <summary>
        /// 创建表
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost]
        public string CreateTable([FromBody] CreateTableReq req)
        {
            string tableName = req.TableName;
            List<TableInfo> tableInfo = req.TableInfos;
            if(tableName == null||tableInfo.Count==0) {
                return "数据不能为空";
            }
            string sql = @"CREATE TABLE ""public""." + tableName+"("+ "id varchar(255) COLLATE \"pg_catalog\".\"default\" NOT NULL,";
            string explanation = "";
            int type = 0;
            for (int i = 0; i < tableInfo.Count; i++) {
                TableInfo table = tableInfo[i];
                if ("id".Equals(table.Name.ToLower())){
                    continue;
                }
                sql = sql  +table.Name+" "+ table.Type;
                if (!table.Name.IsNullOrEmpty()) {
                    explanation = explanation + "COMMENT ON COLUMN \"public\"." + tableName + "." + table.Name + " Is "+"'"+ table.Explanation+"'"+";" ;
                }
                if ("varchar".Equals(table.Name.ToLower())) { 
                    sql = sql +"("+255+")";
                }
                if (table.Type.Contains("geom")) { 
                 type = 1;
                }
                /*if (table.IsNull) {
                    sql = sql+" "+"NOT NUll";
                }*/
                sql = sql + ",";
                if (tableInfo.Count-1==i) {
                    sql = sql + "CONSTRAINT "+ tableName +"_pkey PRIMARY KEY (\"id\"));";
                }
            }
            Console.WriteLine(sql);
             int count = client.Ado.ExecuteCommand(sql);
            Console.WriteLine(count);
            string sql1 = "ALTER TABLE \"public\"." + tableName+ " OWNER TO \"postgres\"";
            client.Ado.ExecuteCommand(sql1);
            addExplain(explanation);
            SysUser user  = auth.GetCurrentUser().User;
            string sql22 = "insert into table_record (\"TableName\",\"Type\",\"ColumnJson\",\"CreateUser\") values('" + tableName+"'," + type+",'"+ String.Join(":",tableInfo.Select(
                p=> $"{p.Name},{p.Type},{p.Explanation}"))+ "','"+user.Account+"')";
            client.Ado.ExecuteCommand(sql22);
            return "创建成功";
        }

        [HttpPost]
        public string CreateView([FromBody] CreateViewReq req) {
            int count = client.Ado.ExecuteCommand(req.sql);
            return "创建成功";
        }

        [HttpPost]
        public List<TableInfo> UploadExcel(UploadExcelReq req)
        {
            using (var workbook = new XLWorkbook(req.file.OpenReadStream())){
                string tableName = req.tableName;
                var wooksheet = workbook.Worksheet(1);
                IXLRows row =  wooksheet.RowsUsed();
                 List<IXLRow> rowCells =  row.ToList();

                 IXLRow  row1 =  rowCells[0];
                IXLCells cells =  row1.CellsUsed();
                
               string sqltable = @"CREATE TABLE if not exists ""public""." + "table_relation_record " + "(" + "id varchar(255) COLLATE \"pg_catalog\".\"default\" NOT NULL," +
                    "name varchar(32) COLLATE \"pg_catalog\".\"default\"," +
                    "relation text COLLATE \"pg_catalog\".\"default\","+
                    " CONSTRAINT \"table_relation_record_pkey\" PRIMARY KEY (\"id\"))\r\n;" +
                    "ALTER TABLE \"public\".\"table_relation_record\"    OWNER TO \"postgres\";";

                
                addExplain(sqltable);
                string sql = @"CREATE TABLE ""public""." + tableName + "(" + "id varchar(255) COLLATE \"pg_catalog\".\"default\" NOT NULL,";
                string explanation = "";
                List<TableInfo>  listTableInfo = new List<TableInfo>();

                int k = 0;
                JsonObject json = new JsonObject();
                foreach (IXLCell cell in row1.CellsUsed())
                {
                    if (cell.GetString().IsNullOrEmpty()) { 
                    break;}
                    json.Add(cell.GetString(), "cloum" + k);
                    TableInfo tableInfo = new TableInfo();
                    tableInfo.Name = "cloum" + k;
                    tableInfo.Type = "varchar";
                   // tableInfo.Length = 255;
                    tableInfo.Explanation = cell.GetString();
                    listTableInfo.Add(tableInfo);
                    sql = sql + "cloum" + k + " " + "varchar(255),";
                    explanation = explanation + "COMMENT ON COLUMN \"public\"." + tableName + "." + "cloum" + k + " Is " + "'" + cell.GetString() + "'" + ";";
                    k++;
                }
                Dictionary<String, Object> dict = new Dictionary<String, Object>();
                dict.Add("id", Guid.NewGuid());
                dict.Add("name", tableName);
                dict.Add("relation", json.ToJsonString());
                client.Insertable(dict).AS("table_relation_record").ExecuteCommand();
                sql = sql + "CONSTRAINT " + tableName + "_pkey PRIMARY KEY (\"id\"));";
                
                string sql1 = "ALTER TABLE \"public\"." + tableName + " OWNER TO \"postgres\"";
                addExplain(sql);
                addExplain(sql1);
                addExplain(explanation);
                var count =  wooksheet.RowCount();
                
                List<Dictionary<String,Object>> listmap = new List<Dictionary<String, Object>>();

                foreach (IXLRow rowValue in wooksheet.RowsUsed()) {
                    if (rowValue.RowNumber() == 1) {

                        continue;
                    }
                   
                    Dictionary<String, Object> map = new Dictionary<String, Object>();
                    map.Add("id", Guid.NewGuid());
                    int g = 0;
                    foreach (IXLCell cell in rowValue.CellsUsed()) {
                        map.Add("cloum" + g, cell.GetString());
                           g++;
                    }
                    listmap.Add(map);

                }
               
                client.Insertable(listmap).AS(tableName).ExecuteCommand();
                return listTableInfo;
            }

           
        }
        [HttpPost]
        public string UpdateTable([FromBody] CreateTableReq req)
        {
            List<TableInfo> infos = req.TableInfos;
            string sql = "";
            foreach (TableInfo info in infos) {
                if (!info.YuanName.IsNullOrEmpty())
                {
                   sql = sql + @"ALTER TABLE ""public""."+req.TableName+"RENAME COLUMN"+info.YuanName + " TO " + info.Name+ ";";
                }
            }
            if (!sql.IsNullOrEmpty()) { addExplain(sql); }
            
            return "创建成功";
        }
            public void addExplain(String sql) {
            client.Ado.ExecuteCommand(sql);
        }


        public bool CheckTableExist(string tableName)
        {

            string sql = "SELECT COUNT(*) FROM information_schema.tables WHERE  table_name =  '" + tableName + "';";

            int count = client.Ado.GetInt(sql);
            if (count > 0)
            {
                return true;
            }
            else { return false; }


        }
    }
}