import Common
import Inject
import SwiftUI

// MARK: - PrimaryButtonStyle

struct PrimaryButtonStyle: ButtonStyle {
  func makeBody(configuration: Self.Configuration) -> some View {
    configuration.label
      .textStyle(.primaryButton)
      .padding(.vertical, .grid(1))
      .padding(.horizontal, .grid(2))
      .background {
        LinearGradient.easedGradient(colors: [
          Color.DS.Background.accent.lighten(by: 0.07),
          Color.DS.Background.accent,
          Color.DS.Background.accent.darken(by: 0.1),
        ], startPoint: .topLeading, endPoint: .bottomTrailing)
          .continuousCornerRadius(.grid(1))
          .shadow(color: Color.DS.Background.accent.opacity(configuration.isPressed ? 0 : 0.7), radius: 8, x: 0, y: 0)
      }
      .scaleEffect(configuration.isPressed ? 0.95 : 1)
      .animation(.gentleBounce(), value: configuration.isPressed)
  }
}

extension View {
  func primaryButtonStyle() -> some View {
    buttonStyle(PrimaryButtonStyle())
  }
}

// MARK: - SecondaryButtonStyle

struct SecondaryButtonStyle: ButtonStyle {
  func makeBody(configuration: Self.Configuration) -> some View {
    configuration.label
      .textStyle(.secondaryButton)
      .padding(.grid(2))
      .padding(.horizontal, .grid(2))
      .background {
        LinearGradient.easedGradient(colors: [
          Color.DS.Background.accentAlt.lighten(by: 0.03),
          Color.DS.Background.accentAlt.darken(by: 0.07),
          Color.DS.Background.accentAlt.darken(by: 0.1),
        ], startPoint: .topLeading, endPoint: .bottomTrailing)
          .continuousCornerRadius(.grid(2))
          .shadow(color: Color.DS.Background.accentAlt.darken(by: 0.2).opacity(configuration.isPressed ? 0 : 0.7), radius: 4, x: 0, y: 0)
      }
      .scaleEffect(configuration.isPressed ? 0.95 : 1)
      .animation(.gentleBounce(), value: configuration.isPressed)
  }
}

extension View {
  func secondaryButtonStyle() -> some View {
    buttonStyle(SecondaryButtonStyle())
  }
}

// MARK: - TertiaryButtonStyle

struct TertiaryButtonStyle: ButtonStyle {
  func makeBody(configuration: Self.Configuration) -> some View {
    configuration.label
      .textStyle(.secondaryButton)
      .padding(.grid(2))
      .padding(.horizontal, .grid(2))
      .background {
        Color.DS.Background.accent.opacity(0.2)
          .continuousCornerRadius(.grid(2))
      }
      .scaleEffect(configuration.isPressed ? 0.95 : 1)
      .animation(.gentleBounce(), value: configuration.isPressed)
  }
}

extension View {
  func tertiaryButtonStyle() -> some View {
    buttonStyle(TertiaryButtonStyle())
  }
}

// MARK: - IconButtonStyle

struct IconButtonStyle: ButtonStyle {
  var isPrimary = true
  @State var feedbackGenerator = UISelectionFeedbackGenerator()

  func makeBody(configuration: Self.Configuration) -> some View {
    configuration.label
      .foregroundColor(isPrimary ? .DS.Text.accent : .DS.Text.base)
      .font(isPrimary ? .DS.action : .DS.actionSecondary)
      .frame(width: 30, height: 30)
      .padding(.grid(2))
      .scaleEffect(configuration.isPressed ? 0.9 : 1)
      .contentShape(Rectangle())
      .animation(.gentleBounce(), value: configuration.isPressed)
      .onChange(of: configuration.isPressed) { _ in
        feedbackGenerator.selectionChanged()
      }
  }
}

extension View {
  func iconButtonStyle() -> some View {
    buttonStyle(IconButtonStyle(isPrimary: true))
  }

  func secondaryIconButtonStyle() -> some View {
    buttonStyle(IconButtonStyle(isPrimary: false))
  }
}

// MARK: - RecordButtonStyle

struct RecordButtonStyle: ButtonStyle {
  func makeBody(configuration: Self.Configuration) -> some View {
    configuration.label
      .scaleEffect(configuration.isPressed ? 0.95 : 1)
      .animation(.gentleBounce(), value: configuration.isPressed)
  }
}

extension View {
  func recordButtonStyle() -> some View {
    buttonStyle(RecordButtonStyle())
  }
}

// MARK: - CardStyle

struct CardStyle: ViewModifier {
  var isPrimary: Bool

  func body(content: Content) -> some View {
    content
      .cornerRadius(.grid(4))
      .background {
        ZStack {
          LinearGradient.easedGradient(colors: [
            .DS.Background.secondary,
            .DS.Background.secondary.darken(by: 0.02),
            .DS.Background.secondary.darken(by: 0.04),
          ], startPoint: .topLeading, endPoint: .bottom)

          LinearGradient.easedGradient(colors: [
            .DS.Background.secondary.lighten(by: 0.07),
            .DS.Background.secondary,
          ], startPoint: .topLeading, endPoint: .bottomTrailing)
            .opacity(isPrimary ? 1 : 0)

          Color.DS.Background.accentAlt.blendMode(.multiply)
            .opacity(isPrimary ? 0.3 : 0)

          RoundedRectangle(cornerRadius: .grid(4))
            .strokeBorder(
              LinearGradient.easedGradient(colors: [
                .DS.Background.secondary.lighten(by: 0.01),
                .DS.Background.secondary,
              ], startPoint: .topLeading, endPoint: .bottom),
              lineWidth: 1
            )
            .opacity(isPrimary ? 0 : 1)

          RoundedRectangle(cornerRadius: .grid(4))
            .strokeBorder(
              LinearGradient.easedGradient(colors: [
                .DS.Background.secondary.lighten(by: 0.08),
                .DS.Background.secondary.lighten(by: 0.02),
              ], startPoint: .topLeading, endPoint: .bottomTrailing),
              lineWidth: 1
            )
            .opacity(isPrimary ? 1 : 0)
        }
        .continuousCornerRadius(.grid(4))
        .shadow(color: .DS.Background.accentAlt.darken(by: 0.4).opacity(isPrimary ? 1 : 0),
                radius: isPrimary ? 50 : 5,
                x: 0,
                y: isPrimary ? 7 : 1)
      }
  }
}

extension View {
  func cardStyle(isPrimary: Bool = true) -> some View {
    modifier(CardStyle(isPrimary: isPrimary))
  }
}
