@use "sass:math";
@use "sass:string";
@use "sass:meta";
@use "../config/feature-flags" as config-flags;
@use "../config/breakpoints" as config-breakpoint;
@use "../config/spacing" as config-spacing;
@use "../functions/feature-flags" as fn-flags;
@use "../functions/units" as fn-units;

// @component Spacing
// @description Controls element margins, padding, gaps, and spacing between children
// @example
// <!-- Padding -->
// <div class="p-4">All sides padding</div>
// <div class="px-4 py-2">Horizontal and vertical padding</div>
// <div class="pt-2 pb-4">Top and bottom padding</div>
// <!-- Margins -->
// <div class="m-4">All sides margin</div>
// <div class="mt-4">Top margin only</div>
// <div class="mx-auto">Horizontally centered</div>
// <!-- Gap (for flex/grid containers) -->
// <div class="flex gap-4">
//  <div>Item 1</div>
//  <div>Item 2</div>
// </div>
// <!-- Responsive spacing -->
// <div class="p-2 p-4@md p-6@lg">
//  Padding increases at each breakpoint
// </div>
// <!-- Child spacing -->
// <div class="space-y-4">
//  <div>First child</div>
//  <div>Second child (margin-top: 1rem)</div>
//  <div>Third child (margin-top: 1rem)</div>
// </div>
// @classes
// Padding:
// - p-{size}: Padding on all sides
// - px-{size}: Horizontal padding (left and right)
// - py-{size}: Vertical padding (top and bottom)
// - pt-{size}, pr-{size}, pb-{size}, pl-{size}: Individual side padding
// Margin:
// - m-{size}: Margin on all sides
// - mx-{size}: Horizontal margin (left and right)
// - my-{size}: Vertical margin (top and bottom)
// - mt-{size}, mr-{size}, mb-{size}, ml-{size}: Individual side margin
// - mx-auto, ml-auto, mr-auto: Auto margin for alignment
// Gap:
// - gap-{size}: Gap between flex/grid children (all directions)
// - gap-x-{size}: Horizontal gap between children (column-gap)
// - gap-y-{size}: Vertical gap between children (row-gap)
// Child Spacing:
// - space-x-{size}: Horizontal space between children
// - space-y-{size}: Vertical space between children
// @responsive
// All spacing classes support responsive variants using @breakpoint suffix:
// - p-4@md: 1rem padding on medium screens and up
// - mt-8@lg: 2rem top margin on large screens
// - gap-2@xl: 0.5rem gap on extra large screens
// @customization
// Spacing values are defined in the $spacings map in variables.scss
// Typically follows a scale where higher numbers mean more spacing
// @see flex, grid, display

// -----------------------------------------------
// PADDING MIXINS
// -----------------------------------------------

// @mixin p
// @description Sets padding on all sides
// @param {Number|String} $val - Padding value
@mixin p($val) {
    padding: fn-units.fix-units($val);
}

// @mixin px
// @description Sets horizontal padding (left and right)
// @param {Number|String} $val - Padding value
@mixin px($val) {
    padding-inline: fn-units.fix-units($val);
}

// @mixin py
// @description Sets vertical padding (top and bottom)
// @param {Number|String} $val - Padding value
@mixin py($val) {
    padding-block: fn-units.fix-units($val);
}

// @mixin pt
// @description Sets padding-top
// @param {Number|String} $val - Padding value
@mixin pt($val) {
    padding-top: fn-units.fix-units($val);
}

// @mixin pr
// @description Sets padding-right
// @param {Number|String} $val - Padding value
@mixin pr($val) {
    padding-right: fn-units.fix-units($val);
}

// @mixin pb
// @description Sets padding-bottom
// @param {Number|String} $val - Padding value
@mixin pb($val) {
    padding-bottom: fn-units.fix-units($val);
}

// @mixin pl
// @description Sets padding-left
// @param {Number|String} $val - Padding value
@mixin pl($val) {
    padding-left: fn-units.fix-units($val);
}

// -----------------------------------------------
// MARGIN MIXINS
// -----------------------------------------------

// @mixin m
// @description Sets margin on all sides
// @param {Number|String} $val - Margin value
@mixin m($val) {
    margin: fn-units.fix-units($val);
}

// @mixin mx
// @description Sets horizontal margin (left and right)
// @param {Number|String} $val - Margin value
@mixin mx($val) {
    margin-inline: fn-units.fix-units($val);
}

// @mixin my
// @description Sets vertical margin (top and bottom)
// @param {Number|String} $val - Margin value
@mixin my($val) {
    margin-block: fn-units.fix-units($val);
}

// @mixin mt
// @description Sets margin-top
// @param {Number|String} $val - Margin value
@mixin mt($val) {
    margin-top: fn-units.fix-units($val);
}

// @mixin mr
// @description Sets margin-right
// @param {Number|String} $val - Margin value
@mixin mr($val) {
    margin-right: fn-units.fix-units($val);
}

// @mixin mb
// @description Sets margin-bottom
// @param {Number|String} $val - Margin value
@mixin mb($val) {
    margin-bottom: fn-units.fix-units($val);
}

// @mixin ml
// @description Sets margin-left
// @param {Number|String} $val - Margin value
@mixin ml($val) {
    margin-left: fn-units.fix-units($val);
}

// @mixin ml-auto
// @description Sets margin-left to auto
@mixin ml-auto {
    margin-left: auto;
}

// @mixin mr-auto
// @description Sets margin-right to auto
@mixin mr-auto {
    margin-right: auto;
}

// @mixin mx-auto
// @description Centers element horizontally using auto margins
@mixin mx-auto {
    @include ml-auto;
    @include mr-auto;
}

// -----------------------------------------------
// INSET MIXINS
// -----------------------------------------------

// @mixin inset
// @description Sets all inset properties (top, right, bottom, left)
// @param {Number|String} $val - Inset value
@mixin inset($val) {
    $val: fn-units.fix-units($val);

    inset: fn-units.fix-units($val);
}

// @mixin inset-x
// @description Sets horizontal inset properties (left and right)
// @param {Number|String} $val - Inset value
@mixin inset-x($val) {
    $val: fn-units.fix-units($val);

    left: $val;
    right: $val;
}

// @mixin inset-y
// @description Sets vertical inset properties (top and bottom)
// @param {Number|String} $val - Inset value
@mixin inset-y($val) {
    $val: fn-units.fix-units($val);

    top: $val;
    bottom: $val;
}

// @mixin inset-auto
// @description Sets all inset properties to auto
@mixin inset-auto {
    inset: auto;
}

// @mixin inset-x-auto
// @description Sets horizontal inset properties to auto
@mixin inset-x-auto {
    left: auto;
    right: auto;
}

// @mixin inset-y-auto
// @description Sets vertical inset properties to auto
@mixin inset-y-auto {
    top: auto;
    bottom: auto;
}

// -----------------------------------------------
// SPACING MIXINS
// -----------------------------------------------

// @mixin space-y
// @description Adds vertical spacing between direct children
// @param {Number|String} $i - Space amount
@mixin space-y($i) {
    & > * + * {
        margin-top: fn-units.fix-units($i);
    }
}

// @mixin space-x
// @description Adds horizontal spacing between direct children
// @param {Number|String} $i - Space amount
@mixin space-x($i) {
    & > * + * {
        margin-left: fn-units.fix-units($i);
    }
}

// -----------------------------------------------
// GAP MIXINS
// -----------------------------------------------

// @mixin gap
// @description Sets gap between grid/flex children
// @param {Number|String} $val - Gap value
@mixin gap($val) {
    $val: fn-units.fix-units($val);

    gap: $val;

    --flex-gap: #{$val};
}

// @mixin gap-x
// @description Sets horizontal gap between grid/flex children
// @param {Number|String} $val - Gap value
@mixin gap-x($val) {
    $val: fn-units.fix-units($val);

    column-gap: $val;

    --flex-gap: #{$val};
}

// @mixin gap-y
// @description Sets vertical gap between grid/flex children
// @param {Number|String} $val - Gap value
@mixin gap-y($val) {
    $val: fn-units.fix-units($val);

    row-gap: $val;

    --flex-gap: #{$val};
}

@if fn-flags.feature-enabled("spacing") {
    // -----------------------------------------------
    // AUTO MARGIN UTILITY CLASSES
    // -----------------------------------------------

    #{config-flags.$parent-selector} .mx-auto {
        @include mx-auto;
    }

    #{config-flags.$parent-selector} .ml-auto {
        @include ml-auto;
    }

    #{config-flags.$parent-selector} .mr-auto {
        @include mr-auto;
    }

    // -----------------------------------------------
    // GAP AUTO CLASS
    // -----------------------------------------------

    #{config-flags.$parent-selector} .gap-auto {
        gap: auto;
    }

    // Auto inset utility classes
    #{config-flags.$parent-selector} .inset-auto {
        @include inset-auto;
    }

    #{config-flags.$parent-selector} .inset-x-auto {
        @include inset-x-auto;
    }

    #{config-flags.$parent-selector} .inset-y-auto {
        @include inset-y-auto;
    }

    // -----------------------------------------------
    // SPACING CLASSES
    // -----------------------------------------------

    @each $key, $value in config-spacing.$spacings {
        // Padding classes
        #{config-flags.$parent-selector} .p-#{$key} {
            @include p($value);
        }
        #{config-flags.$parent-selector} .px-#{$key} {
            @include px($value);
        }
        #{config-flags.$parent-selector} .py-#{$key} {
            @include py($value);
        }
        #{config-flags.$parent-selector} .pt-#{$key} {
            @include pt($value);
        }
        #{config-flags.$parent-selector} .pr-#{$key} {
            @include pr($value);
        }
        #{config-flags.$parent-selector} .pb-#{$key} {
            @include pb($value);
        }
        #{config-flags.$parent-selector} .pl-#{$key} {
            @include pl($value);
        }

        // Margin classes
        #{config-flags.$parent-selector} .m-#{$key} {
            @include m($value);
        }
        #{config-flags.$parent-selector} .mx-#{$key} {
            @include mx($value);
        }
        #{config-flags.$parent-selector} .my-#{$key} {
            @include my($value);
        }
        #{config-flags.$parent-selector} .mt-#{$key} {
            @include mt($value);
        }
        #{config-flags.$parent-selector} .mr-#{$key} {
            @include mr($value);
        }
        #{config-flags.$parent-selector} .mb-#{$key} {
            @include mb($value);
        }
        #{config-flags.$parent-selector} .ml-#{$key} {
            @include ml($value);
        }

        // Gap classes
        #{config-flags.$parent-selector} .gap-#{$key} {
            @include gap($value);
        }
        #{config-flags.$parent-selector} .gap-x-#{$key} {
            @include gap-x($value);
        }
        #{config-flags.$parent-selector} .gap-y-#{$key} {
            @include gap-y($value);
        }

        // Space classes
        #{config-flags.$parent-selector} .space-x-#{$key} {
            @include space-x($value);
        }
        #{config-flags.$parent-selector} .space-y-#{$key} {
            @include space-y($value);
        }

        #{config-flags.$parent-selector} .inset-#{$key} {
            @include inset($value);
        }
        #{config-flags.$parent-selector} .inset-x-#{$key} {
            @include inset-x($value);
        }
        #{config-flags.$parent-selector} .inset-y-#{$key} {
            @include inset-y($value);
        }
    }

    // -----------------------------------------------
    // RESPONSIVE SPACING CLASSES
    // -----------------------------------------------

    @each $breakpoint, $width in config-breakpoint.$breakpoints {
        @media (min-width: #{$width}) {
            #{config-flags.$parent-selector} .mx-auto\@#{$breakpoint} {
                @include mx-auto;
            }
            #{config-flags.$parent-selector} .ml-auto\@#{$breakpoint} {
                @include ml-auto;
            }
            #{config-flags.$parent-selector} .mr-auto\@#{$breakpoint} {
                @include mr-auto;
            }
            #{config-flags.$parent-selector} .inset-auto\@#{$breakpoint} {
                @include inset-auto;
            }
            #{config-flags.$parent-selector} .inset-x-auto\@#{$breakpoint} {
                @include inset-x-auto;
            }
            #{config-flags.$parent-selector} .inset-y-auto\@#{$breakpoint} {
                @include inset-y-auto;
            }

            // Generate utilities from spacing map
            @each $key, $value in config-spacing.$spacings {
                // Padding classes
                #{config-flags.$parent-selector} .p-#{$key}\@#{$breakpoint} {
                    @include p($value);
                }
                #{config-flags.$parent-selector} .px-#{$key}\@#{$breakpoint} {
                    @include px($value);
                }
                #{config-flags.$parent-selector} .py-#{$key}\@#{$breakpoint} {
                    @include py($value);
                }
                #{config-flags.$parent-selector} .pt-#{$key}\@#{$breakpoint} {
                    @include pt($value);
                }
                #{config-flags.$parent-selector} .pr-#{$key}\@#{$breakpoint} {
                    @include pr($value);
                }
                #{config-flags.$parent-selector} .pb-#{$key}\@#{$breakpoint} {
                    @include pb($value);
                }
                #{config-flags.$parent-selector} .pl-#{$key}\@#{$breakpoint} {
                    @include pl($value);
                }

                // Margin classes
                #{config-flags.$parent-selector} .m-#{$key}\@#{$breakpoint} {
                    @include m($value);
                }
                #{config-flags.$parent-selector} .mx-#{$key}\@#{$breakpoint} {
                    @include mx($value);
                }
                #{config-flags.$parent-selector} .my-#{$key}\@#{$breakpoint} {
                    @include my($value);
                }
                #{config-flags.$parent-selector} .mt-#{$key}\@#{$breakpoint} {
                    @include mt($value);
                }
                #{config-flags.$parent-selector} .mr-#{$key}\@#{$breakpoint} {
                    @include mr($value);
                }
                #{config-flags.$parent-selector} .mb-#{$key}\@#{$breakpoint} {
                    @include mb($value);
                }
                #{config-flags.$parent-selector} .ml-#{$key}\@#{$breakpoint} {
                    @include ml($value);
                }

                #{config-flags.$parent-selector} .gap-#{$key}\@#{$breakpoint} {
                    gap: $value;
                }
                #{config-flags.$parent-selector} .gap-x-#{$key}\@#{$breakpoint} {
                    column-gap: $value;
                }
                #{config-flags.$parent-selector} .gap-y-#{$key}\@#{$breakpoint} {
                    row-gap: $value;
                }

                // Space classes
                #{config-flags.$parent-selector} .space-x-#{$key}\@#{$breakpoint} {
                    @include space-x($value);
                }
                #{config-flags.$parent-selector} .space-y-#{$key}\@#{$breakpoint} {
                    @include space-y($value);
                }
                #{config-flags.$parent-selector} .inset-#{$key}\@#{$breakpoint} {
                    @include inset($value);
                }
                #{config-flags.$parent-selector} .inset-x-#{$key}\@#{$breakpoint} {
                    @include inset-x($value);
                }
                #{config-flags.$parent-selector} .inset-y-#{$key}\@#{$breakpoint} {
                    @include inset-y($value);
                }
            }
        }
    }
}
