import Axios from 'axios'
import simpleGit from 'simple-git'
import { prompt } from 'enquirer'
import * as fs from 'fs'
import path from 'path'

const axios = Axios.create({
    baseURL: 'http://gitlab.yslocal.com',
    withCredentials: true,
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        Host: 'gitlab.yslocal.com'
    }
})

/** 导出服务 */
export default class CommandGitDeepClone {
    opt!: { Cookie: string }

    async command() {
        // if don't has options, exec user input
        await this.inputGitUser()
        // ! login 实现太难, 直接贴 cookie 吧
        // pull git group
        let groups = await this.pullAllGroup()
        // filter should clone group
        groups = await this.filterCloneGroup(groups)
        // pull all projects info
        const projects = await this.pullProject(groups)
        // cloen
        console.log('> 共计:', projects.length, '个项目')
        this.clones(projects)
    }

    async filterCloneGroup(groups: Array<string>): Promise<Array<string>> {
        const { isConfirm } = (await prompt({
            type: 'select',
            name: 'isConfirm',
            message: 'clones project from all group?',
            choices: ['yes', 'no']
        })) as any
        if (isConfirm !== 'yes') {
            try {
                const { selected } = (await prompt({
                    type: 'multiselect',
                    name: 'selected',
                    message: 'Pick your favorite colors',
                    choices: groups
                })) as any
                groups = selected
            } catch (error) {
                //
            }
        }
        return groups
    }

    /** if can't get params in command, that get git user in readline */
    async inputGitUser() {
        const query = []
        let cookie: any
        if (!this.opt?.Cookie) {
            query.push({
                type: 'input',
                name: 'Cookie',
                message: 'gitlab session (登录后, 从cookie中查看)'
            })
            const response: { Cookie: string } = await prompt(query)
            cookie = response.Cookie
        } else {
            cookie = this.opt.Cookie
        }
        // input
        this.opt = { Cookie: cookie.includes('=') ? cookie : '_gitlab_session=' + cookie }
    }

    /** pull git group from your gitlab */
    async pullAllGroup(): Promise<Array<string>> {
        const { data } = await axios.get('/dashboard/groups.json', {
            headers: { Cookie: this.opt.Cookie }
        })

        const groups = data.map((item: any) => {
            return item['relative_path']?.replace(/^\//, '')
        })

        return groups
    }
    async pullProject(groups: Array<string>, pageIndex: number = 1): Promise<Array<string>> {
        console.log('fetching...')
        let projects: Array<string> = []
        for (const group of groups) {
            const p = path.normalize(`/groups/${group}/-/children.json${pageIndex > 1 ? '?page=' + pageIndex : ''}`)

            console.log('> pull', p)
            const { data, headers } = await axios.get(p, {
                headers: { Cookie: this.opt.Cookie }
            })
            for (const project of data) {
                const { type, relative_path } = project
                if (type === 'group') {
                    const children = await this.pullProject([relative_path])
                    projects = [...projects, ...children]
                } else {
                    projects.push(relative_path)
                }
            }
            if (headers['x-total-pages'] > 1 && pageIndex < headers['x-total-pages']) {
                const children = await this.pullProject(groups, pageIndex + 1)
                projects = [...projects, ...children]
            }
        }
        return projects
    }
    /** 执行 clone */
    async clones(projects: Array<string>) {
        let p
        try {
            const inp = (await prompt({
                type: 'input',
                name: 'p',
                message: '输入一个本地地址, 用来clone 这些仓库:'
            })) as any
            p = inp.p
        } catch (error) {
            //
        }
        if (!fs.existsSync(p)) return console.log(`> path not exist:`, p)
        if (!fs.statSync(p).isDirectory()) return console.log(`> path not a directory:`, p)
        for (const pro of projects) {
            const repo = `http://gitlab.yslocal.com${pro}`
            if (fs.existsSync(p + pro)) continue
            await simpleGit().clone(repo, p + pro)
            console.log('> cloned', repo)
        }
    }
}
