import { STORAGE_KEY } from '../utils';
import Ajv from 'ajv';

export interface Table {
  name: string;
  value: Array<TableValue>;
}
export interface TableValue {
  dataIndex: string;
  visible: number;
}
export interface State {
  lotId: string;
  table: Table[];
}

const ajv = new Ajv();
require('ajv-keywords')(ajv, 'transform');

/**
 * 缓存核心处理类
 * 严格使用 ajv 验证本地缓存数据的正确性，如果不正确，将直接清空所有缓存数据
 */
export default class TCOLocalStorage {
  static getState() {
    let state: State[] = [];
    try {
      state = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
    } catch (_) {}

    // const test = [
    //   {
    //     lotId: '123123',
    //     table: [
    //       {
    //         name: 'foo',
    //         value: [
    //           {
    //             dataIndex: 'id',
    //             visible: 1
    //           },
    //           {
    //             dataIndex: 'real_views',
    //             visible: 1
    //           },
    //           {
    //             dataIndex: 'title',
    //             visible: 0
    //           },
    //           {
    //             dataIndex: 'user,name',
    //             visible: 1
    //           }
    //         ]
    //       }
    //     ]
    //   }
    // ];

    const schema = TCOLocalStorage.getSchema();
    const validate = ajv.compile(schema);
    // const valid = validate(test);
    const valid = validate(state);
    if (!valid) {
      console.log(validate.errors);
      // 验证不通过，直接重置为空数组
      state = [];
      // 清空storage
      localStorage.removeItem(STORAGE_KEY);
    }
    return state;
  }
  constructor(private state: State[] = []) {}

  static getSchema() {
    const tableValueSchema = {
      type: 'array',
      items: {
        type: 'object',
        properties: {
          dataIndex: {
            type: 'string',
            transform: ['trim'],
            minLength: 1
          },
          visible: {
            type: 'integer'
          }
        },
        required: ['dataIndex', 'visible']
      },
      minItems: 1
    };
    const tableSchema = {
      type: 'array',
      items: {
        type: 'object',
        properties: {
          name: {
            type: 'string',
            transform: ['trim'],
            minLength: 1
          },
          value: tableValueSchema
        },
        required: ['name', 'value']
      },
      minItems: 1
    };
    const schema = {
      type: 'array',
      items: {
        type: 'object',
        properties: {
          lotId: {
            type: 'string',
            transform: ['trim'],
            minLength: 1
          },
          table: tableSchema
        },
        required: ['lotId', 'table']
      },
      minItems: 1
    };
    return schema;
  }
  get(lotId: string): State;
  get(lotId: string, tableName: string): Table;
  get(lotId: string, tableName?: string): State | Table | undefined {
    let obj: State | Table | undefined;
    obj = this.state.find(item => item.lotId === lotId);
    if (tableName) obj = obj?.table.find(item => item.name === tableName);
    return obj;
  }
  set(lotId: string, tableName: string, value: TableValue[]) {
    // 没有传入 lotId 和 tableName 不做任何操作
    if (!(lotId && tableName)) {
      if (process.env.NODE_ENV !== 'production') {
        console.warn(
          `[unity-ant-table warn]: 请确保传入 table-columns-operate 的 lotId 和 tableName 属性，否则不会记录到 localStorage.`
        );
      }
      return;
    }
    // 查看该表格是否存在，存在的话，直接修改
    const table = this.get(lotId, tableName);
    const lot = this.get(lotId);
    if (table) {
      table.value = value;
    }
    // 表格不存在时，查看该车场是否存在，存在时，push 表格操作列数据
    else if (lot) {
      lot.table?.push({
        name: tableName,
        value
      });
    }
    // 都不存在，创建新的车场，push 新的表格操作列
    else {
      this.state.push({
        lotId,
        table: [
          {
            name: tableName,
            value
          }
        ]
      });
    }
    this.save();
  }
  reset(): void;
  reset(lotId?: string, tableName?: string): void;
  reset(lotId?: string, tableName?: string) {
    if (lotId && tableName) {
      const lot = this.get(lotId);
      const table = this.get(lotId, tableName);

      // 当存在 table 时，才进行重置
      if (lot?.table) {
        // 删除对应的 table 数据
        lot.table = lot.table.filter(item => item !== table);
        // 当车场为空时，直接删除车场数据
        if (lot.table.length === 0)
          this.state = this.state.filter(item => item !== lot);
      }

      // 当数组为空时，直接removeItem
      if (this.state.length === 0) this.remove();
      else this.save();
    } else {
      this.state = [];
      this.remove();
    }
  }
  save() {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(this.state));
  }
  remove() {
    localStorage.removeItem(STORAGE_KEY);
  }
}
