// import fs from 'fs-extra';
import path from 'path';
import dedent from 'dedent';
import { createTypegingForBuilders, generateTypedApiFromPath } from '..';
import { compile, expression } from '../..';

describe('Codegen', () => {
    it('should throw when file doesnt exist', async () => {
      const inOutConfig = {
        input: path.resolve(__dirname, './ljdskfhlkjshdfkjasdf'),
      };

      await expect(generateTypedApiFromPath.bind(null, inOutConfig)).rejects.toThrow();
    })

    it('should emit file when file doesnt exist', async () => {
      const inOutConfig = {
        input: path.resolve(__dirname, './example/fixtures'),
      };

      await generateTypedApiFromPath(inOutConfig);
    })


    it('should generate typings', async () => {
      const inOutConfig = {
        input: path.resolve(__dirname, './example/fixtures'),
      };

      class Common {};
      class Type1 {};
      class Type2 {};
      class Type3 {};

      const compiled = compile(
        expression(
          ({ the }) => the(Boolean).and.check(Boolean),
          (isAlive: Boolean, isWell: Boolean) => 'First',
        ),

        expression(
          ({ the }) => the(String).and.writes(String),
          (isAlive: string, isWell: string) => 'First',
        ),

        expression(
          ({ the }) => the(Common).and.type(Boolean),
          (isAlive: Common, isWell: boolean) => 'First',
        ),
      
        expression(
          ({ the }) => the(Boolean).and.well(String),
          ({ the }) => the(Boolean).and.very.well(String),
          (isAlive: Boolean, isWell: Boolean) => 'Second',
        ),

        expression(
          ({ first }) => first(Type1).second(Type2).then.third(Type1),
          ({ first }) => first(Type1).second(Type2).then(Type1),
          (type1 : Type1, type2: Type2, nextType1: Type1) => 'Third',
        ),

        expression(
          ({ first }) => first(Type1).second(Type2).then.fourth(Type3),
          ({ first }) => first(Type1).second(Type2).then(Type3),
          (type1 : Type1, type2: Type2, type3: Type3) => 'Fourth',
        ),
      );

      const typings = await createTypegingForBuilders(inOutConfig, compiled);
      expect(typings).toEqual(dedent`
        /* ------------------------------------
        *  Generated by chai-latte
        *  Please do not edit this file directly
        *  Instead, edit the file './fixtures'
        * ------------------------------------
        */

        import builder from './fixtures';

        type Expressions = typeof builder.__expressions;
        type ExpressionCallback<Idx extends number> = Expressions[Idx][0]['callback'];
        type Arg<Idx extends number, ArgIndex extends number> = Parameters<ExpressionCallback<Idx>>[ArgIndex];
        type Return<Idx extends number> = ReturnType<ExpressionCallback<Idx>>;

        type Root = {
          the: {
            (bool: Arg<0, 0>) : {
              and: {
                check: {
                  (bool: Arg<0, 1>) : Return<0>;
                };
                well: {
                  (str: Arg<3, 1>) : Return<3>;
                };
                very: {
                  well: {
                    (str: Arg<3, 1>) : Return<3>;
                  };
                };
              };
            };
            (str: Arg<1, 0>) : {
              and: {
                writes: {
                  (str: Arg<1, 1>) : Return<1>;
                };
              };
            };
            (common: Arg<2, 0>) : {
              and: {
                type: {
                  (bool: Arg<2, 1>) : Return<2>;
                };
              };
            };
          };
          first: {
            (type1: Arg<4, 0>) : {
              second: {
                (type2: Arg<4, 1>) : {
                  then: {
                    third: {
                      (type1: Arg<4, 2>) : Return<4>;
                    };
                    fourth: {
                      (type3: Arg<5, 2>) : Return<5>;
                    };
                    (type1: Arg<4, 2>) : Return<4>;
                    (type3: Arg<5, 2>) : Return<5>;
                  };
                };
              };
            };
          };
        };

        export default builder as unknown as Root;
      `)
    })
});
